选择一个微服务部署策略

动机

部署一个单体应用意味着运行多个相同的单个副本,并且通常是比较大的应用。你通常配置N个服务器(物理或虚拟),并且在每个上面跑M个应用的实例。单体应用的部署不总是很简单的,但是比部署微服务简单多了。

微服务包含很多服务。服务又可能是用不同的语言和框架写的。每个服务都是一个有自己特定部署、资源、缩放和监控需求的小型应用。比如你需要根据服务来为每个服务启动一定量的实例。每个服务必须被提供合适的CPU、内存和IO资源。更具挑战的是部署必须可靠和具有成本效益。

多服务单主机模式

每个服务实例跑在一个或多个主机上的知名端口上运行。

优点:

  • 资源使用率高。多个服务实例共享服务器和操作系统,如果进程或进程组运行多个服务实例则更加有效。比如多个web应用共享同一个Tomcat服务器和JVM。
  • 部署服务的速度快。只需要把服务复制到主机上并启动。如果是Java,复制JAR/WAR。其他语言就复制源代码。任何情况下通过网络复制的字节数相对比较小。
  • 启动服务的速度快。因为没有

缺点:

  • 进程之间无隔离。当你可以准确监控每个服务实例的资源利用率时,不能限制每个实例使用的资源。可能会耗尽主机的所有内存和CPU。
  • 部署服务的团队必须知道如何执行部署的细节。

单服务单主机模式

当你使用这个模式,你把每个服务打包成一个虚拟机镜像就像AMI一样。每个服务实例都是使用这个镜像的一个虚拟机。

这是Netflix用来部署其视频流服务的主要方法。 Netflix使用Aminator将其每个服务包装为EC2 AMI。每个正在运行的服务实例是EC2实例。

您可以使用多种工具来构建自己的虚拟机。您可以配置您的持续集成(CI)服务器(例如Jenkins)来调用Aminator将服务打包为EC2 AMI。Packer.io是自动化虚拟机映像创建的另一个选项。与Aminator不同,它支持各种虚拟化技术,包括EC2,DigitalOcean,VirtualBox和VMware。

优点:

  • 每个实例完全隔离。有固定的CPU和内存,不能从其他服务窃取资源。
  • 利用成熟的云设施。比如AWS提供了有用的功能比如负载均衡和自动缩放。
  • 封装服务实现的技术。一旦一个服务被打包成一个虚拟机,它将成为一个黑盒子。虚拟机的管理API变成部署服务的API。部署变得更加简单和可靠。

缺点:

  • 资源利用率低。每个服务都有整个虚拟机的开销。
  • 成本变高。IAAS通常不管实例是否空闲还是繁忙,都会收费。比如AWS提供自动缩放,但是很难快速响应需求变化
  • 部署新版本慢。虚拟机镜像通常构建地很慢、很慢地实例化,还有他们的大小,操作系统的启动时间也是有的。但是并不普遍,也有轻量级虚拟机比如Boxfuse的。

单服务单容器模式

当你用这个模式,每个服务实例都跑在自己的容器。容器是操作系统级的虚拟化。容器包含沙箱中的一个或多个进程。从进程的角度来看,它们有自己的的命名空间和根文件系统。你可以限制容器的内存和CPU。

要使用这个模式,你需要打包你的服务成为一个容器镜像。容器镜像是一个包含了跑服务的应用和库的文件系统。一些容器镜像包含完整的Linux根文件系统。其他是轻量级的。为了部署Java,比如,你构建一个包含Java运行时环境,Tomcat服务器和你的Java应用的镜像就好了。

一旦你打包你的服务成为容器镜像,你可以启动一个或者多个容器。你通常跑多个容器在每个无力主机或者虚拟主机上。你可以用Kubernetes或Marathon去管理你的容器。集群管理器把主机视为资源池。它根据容器容器所需的资源和每个主机上可用的资源来决定放置每个容器的位置。

优点:

  • 便于监控每个服务的开销。因为每个服务之间是独立的服务容器。
  • 与虚拟机一样,封装服务。
  • 构建速度快与虚拟机镜像。比如在我的电脑上用docker只有5秒来打包Spring Boot应用。容器启动也非常快,因为没有冗长的操作系统启动机制。当容器开启之后,服务也会开启。

缺点:

  • 不够成熟与安全。容器也不如虚拟机安全因为共享主机的内核。
  • 需要管理容器镜像与部署架构。除非你用托管容器解决方案比如 Google Container Engine or Amazon EC2 Container Service (ECS), 否则你必须管理运行服务的容器设施和虚拟机设施。
  • 过度的虚拟机花费。容器常被部署在按每个虚拟机价格收费的基础设施上,你可能会承担过度配置虚拟机的额外花费。

有趣的是,容器和虚拟机之间的区别是模糊的。如前所述,Boxfuse VM可以很快构建和启动。Clear Containers旨在创建轻量级虚拟机。Docker最近收购了Unikernel Systems。

还有越来约受欢迎的无服务部署概念。这是一种避开在部署服务在容器还是虚拟机之间的选择的方法。下面我们来看看。

无服务部署

AWS Lambda是无服务部署技术。它支持Java,Node.js,和Python服务。为了部署微服务,你需要打包它并上传到AWS Lambda。你也提供元数据,其中指定调用处理请求的函数的名称。AWS Lambda自动跑足够微服务实例来处理请求。你可以基于内存使用和每个请求花的时间来计费。当然,恶魔在细节上,你将了解到AWS Lambda的限制。但是你和别人都不需要单行任何服务器、虚拟机或者容器方面的问题。

AWS Lambda function是一个无状态的服务。它通常通过调用AWS服务来处理请求。比如当一个图像被传到S3时会触发一个AWS Lambda function,将图插入到DynamoDb图像表中并且将消息发布到Kinesis流中来触发图像处理。一个AWS Lambda function可以触发第三方web服务。

有4个方法去触发一个AWS Lambda function:

  1. 直接的,用一个web服务请求
  2. 自动的,回应来自AWS服务比如S3,DynamoDB, Kinesis, or Simple Email Service的事件
  3. 自动的,通过AWS API网关去处理来自客户端HTTP请求
  4. 定期的,根据cron一样的时间表

AWS Lambda是部署微服务的便捷方式。基于请求的定价意味着你只需支付服务执行的实际操作。并且因为你不需要为基础设施负责,你可以关注在你开发应用上来。

然而有很多限制。不适于部署需要长时间运行的服务,比如从第三方消息代理那处理消息的服务。请求必须在300秒内往完成。服务必须是无状态的,所以理论上AWS Lambda会为每个不同的请求在不同的服务器上跑。他们必须用支持的语言来写。服务也必须很快被启动;因此请求可能超时和被终止。

总结

部署微服务是有挑战的。有用很多语言和框架的多种甚至上百种服务。每个都是有自己部署方式、资源、缩放和监控需求的小型应用。有多服务单主机、单服务单主机、单服务单容器、无服务微服务部署模式可供选择。

Comments