返回 登录
0

微服务的十大戒律(上篇)

微服务(Microservice)开启了分布式计算时代的新纪元。

随着容器技术的出现,部署单元逐渐开始挥别VM模型。比如LXC、Docker、runC和tkt等Linux容器技术,支持多种容器在同一VM里运行,而且每个app组件或app模块可封装在专用容器里,实现DevOps。每个容器包含从OS到运行时间、框架和代码等独立单元运行时所需的一切。

的确,逻辑组合容器可形成一个应用,而一个应用的关键在于编排各种容器实现预期输出。

图片描述

不过人们常有这样一个误解:将传统的单体式应用移至容器,单体式系统(Monolithic system)就会自动转化为微服务架构了。事实当然没这么简单,容器化并不能立刻将一个app转化为一个基于微服务的应用。

要理解微服务,最好想想虚拟化和云吧!在IaaS最初的几年里,许多CIO都声称他们建的是私有云,但实际上,他们只是在铺排虚拟化罢了。同样地,微服务可以用到容器化,但不是每个容器化应用都是微服务。

以下是迈向微服务之路需要注意的十大问题。

微服务的“十大戒律”

图片描述

1. 清楚区分无状态和有状态服务

微服务组成的应用包括无状态和有状态服务。实施有状态服务时理解其制约条件非常重要。如果一个服务依赖于状态,应该将它隔离到某个易访问的专用容器里。

微服务的关键优势之一是快速扩展。和其他分布式计算架构一样,微服务在无状态时扩展性极佳。几秒钟内,各种容器就大面积跨主机部署就位。每个运行服务的容器都是独立的,并不理会其它服务的存在,因此,精确扩展目标服务取代了VM的扩展。注意这种无缝扩展要求服务必须是无状态的。容器的瞬时启停特性让它成为构建微服务架构的理想选择。

图片描述

一个基于微服务的应用也可能包含有状态服务,以关系型数据库管理系统(RDBMS)、NoSQL数据库和文件系统的形式。它们封装为容器后有特殊属性。如果有状态服务将持久化卸载给主机,将会使容器在主机间的port移植变得困难。Flocker和Docker volume plugin技术可以解决这个问题,通过创建分离的持久层,不依赖主机。

通常,有状态服务采用两种方式——卸载持久化给主机或使用高可用云数据存储——来提供一层持久层,但这两种方式都带来新的复杂性:卸载持久化给主机将会使容器在主机间的port移植困难,而高可用数据存储是拿一致性换可用性,这意味着我们的数据模型不得不考虑最终一致性设计。

Flocker技术通过创建一层分离的不依赖主机的持久层来解决主机可移植性问题。而Redis、Cassandra和IBM的Cloudant等云数据存储新技术,通过最小化一致性延迟来最大程度保证可用性。

随着容器技术的进化发展,相信解决有状态服务的问题将变得更加容易。

图片描述

2. 不要共享库或SDK

微服务的前提是基于独立的、细颗粒度的代码单元,这些代码单元均只专注做一件事,而且紧密跟随DRY原则(Don’t Repeat Yourself,“不要自我重复”原则),即系统内每个功能点必有一个单一清楚的权威代表。

每个服务都是一个包含OS、运行时间、框架、第三方库和代码的独立单元。当一个或多个容器依赖同一个库时,可通过主机集中配置来共享依赖关系。这种模型给长时运行增加了复杂性:不仅引发主机关联性问题,而且打破了CI/CD管道机制。升级库或SDK可能以服务中断收场。每个服务应该与其他服务完全独立开来对待。

在某些场景下,通用的库和SDK可以移至专用服务中独立管理,使服务不可变(immutable)。

图片描述

3. 避免主机关联性

这一点在刚才的共享库中也简要提及。对于运行服务的主机我们不做任何假设,主机包含有路径、IP地址、端口号、OS的特定分布和版本信息,以及特定文件、库和SDK的可用性。

只要集群中主机可用,就支持任何符合预定义要求的服务运行。这里的“预定义要求”更靠近“偏硬”的规格,比如CPU类型、存储类型,地域(Region)和可用区(Availability Zone),而不是“偏软”的配置。服务应该与所部署的主机完全独立开来工作。

对于有状态服务,部署在一个专有的持久性(数据量)容器里是合理考量。

4. 每个服务只专注做好一件事

在设计微服务架构时,每个服务必须专注且只专注一件任务。它可以映射到一个函数或一个模块,有清晰明白的边界。这意味着一个容器可以对应一个进程,但事实并非总是如此。

Docker十分支持一个容器运行一个后台进程/daemon的模式,这样容器与VM有了本质的区分。虽然VM能运行在整个堆栈上,但容器拥有堆栈的一部分。举个例子,当对LAMP web应用进行微服务重构时,包括Apache在内的web层运行在一个专有容器里,而MySQL移至另一个容器中。

图片描述

微服务就是一堆模块化、组合化和细颗粒度的单元集合,且每个单元只专注在一件事上。

5. 使用轻量级通信协议

微服务里没有不能变通的通信规则。它采用同步或异步通道以及与平台无关的协议,每个服务都执行简单的请求响应机制。微服务经常暴露一些典型的被REST API调用的HTTP终点( Endpoint)。

当HTTP和REST更偏爱同步通信时,异步通信却在微服务之间备受欢迎。从这点出发,AMQP(Advanced Message Queuing Protocol,高级信息队列协议,它是应用层协议的一个开放标准,为面向消息的中间件设计)也被认为是更优的协议。基于异步通信模型开发微服务架构,虽然有时稍微增加些复杂性,但能明显降低应用延迟、实现事件驱动交互。

现在市面上RabbitMQ和Apache Kafka都是微服务异步通信常用的消息总线技术。而且当消息传输在同一个主机上完成时,容器可通过系统调用实现彼此间的通信,因为他们共享同一个kernel。

下篇预告

  1. 设计清晰的入口点和出口点
  2. 实施自注册和发现机制
  3. 清楚检查规则与限制
  4. 多语言堆栈比单一堆栈更优
  5. 保持独立修订并构建环境
评论