微服务介绍|如何设计微服务架构
通过以上定义和描述,我们基本可以确定微服务的截面特征:
要将微服务实践到生产项目中,首先要考虑一些问题。例如,微服务业务架构如下所示:
在上图所示的架构图中,我们假设商家服务A、订单服务B和产品服务C被拆分到一个微服务应用程序中,并分别进行部署。此时,我们面临着许多可能需要解决的问题,例如:
1.客户如何访问这些服务?
2.各服务之间如何沟通?
3.多微服务如何实现?
4.服务异常宕机怎么办?
这些都是需要逐一解决的问题。
在单个应用的开发中,所有服务都是本地的,前端UI界面和手机APP程序可以直接访问后端服务器程序。
现在它按功能拆分成独立的服务,在独立的进程中运行。如下图所示:
此时,后台有n个服务,前台需要记住管理n个服务。当一个服务离线、更新、升级后,前台和手机APP会重新部署或重新签约,这显然不符合我们拆分的概念。特别是对于当前业务需求的快速发展,业务变更非常频繁。
除了访问管理上的困难,n个小服务的调用也是很大的网络开销。另外,一般的微服务在系统内通常是无状态的,而我们的用户经常跨业务模块操作,需要有状态。这个问题目前无法在这个系统架构中解决。传统上有一个统一的本地维护管理(OAuth)来解决用户登录信息和权限管理,我们称之为授权管理。
基于以上列举的问题,我们采用了一种叫做Gateway(英文API Gateway)的技术方案来解决这些问题。网关的功能主要包括:
API Gateway的实现方式有很多种,可以是软硬一体的盒子,简单的MVC框架,甚至可以是Node.js服务器。它们最重要的作用是为前台(通常是移动应用)提供后台服务的聚合,提供统一的服务出口并将它们解耦,但API Gateway也可能成为单点故障或性能瓶颈。
最后,带有API Gateway的业务架构图更改如下:
所有的微服务都是在自己的进程容器中独立部署和运行的,所以微服务之间的通信就是IPC(进程间通信),翻译过来就是进程间通信。进程间通信的方案已经比较成熟,现在最常见的有两种:同步调用和异步消息调用。
同步呼叫
同步调用简单且一致,但容易出现调用问题,性能体验会更差,尤其是在调用级别很多的情况下。同步调用有两种实现方式:REST和RPC。
基于REST和RPC的特点,我们通常采用以下原则:用REST向系统外部公开,用RPC向系统内部公开调用。
异步消息传递广泛应用于分布式系统中。既能降低调用服务之间的耦合,又能充当调用之间的缓冲,保证消息积压不会冲走被调用方,同时保证调用方的服务体验,继续做自己该做的事,不会被后台性能拖慢。要付出的代价是一致性的弱化,需要接受数据最终的一致性。所谓最终一致性,是指同步可能不会马上完成,会有延迟,但数据同步最终会完成;此外,后台服务一般需要达到幂等性,因为出于性能考虑,消息发送一般会重复进行(保证消息只接收一次,对性能是一个很大的考验)。最后,必须引入一个独立的代理作为中间代理池。
异步消息调用的常见框架有:Kafaka、Notify和MessageQueue。
最后,大多数服务间调用体系结构的实现如下:
在微服务架构中,每个服务一般都有多个副本用于负载平衡。服务可能随时脱机,或者可能添加新的服务节点来响应临时访问压力。这提出了一个新问题:
这就是服务发现、识别和管理的问题。解决多个服务之间的标识,发现的问题一般都是通过注册的方式进行。
具体来说,服务上线时,服务提供者将其服务注册信息注册到一个专门的框架中,通过heartbeat维护一个长链接,实时更新链接信息。服务调用方通过服务管理框架寻址,根据特定的算法找到相应的服务,或者在本地缓存服务的注册信息,从而提高性能。当一个服务离线时,服务管理框架会向其他服务发送服务离线的通知。
常见的服务管理框架有:Zookeeper等框架。
针对上述问题有两种具体的解决方案,即基于客户端的服务注册和发现以及基于服务器的服务注册和发现。
优点是架构简单,扩展灵活,只依赖服务注册中心。缺点是客户端维护调用服务的所有地址在技术上很困难。一般大公司都有成熟的内部框架支持。
好处是所有服务对前台调用者透明,一般采用小公司在云服务上部署的应用。
前面说过,单个应用开发的一个很大的风险就是孤注一掷,一荣俱荣,一损俱损。分发最大的特点就是网络不可靠。这种风险可以通过微服务拆分来降低,但如果没有特别的保障,结局肯定是噩梦。
因此,当我们的系统由一系列服务调用链组成时,我们必须确保任何一个链路故障都不会影响整个链路。相应的手段有很多,比如: