在单体应用向微服务架构演进的过程中,原本的巨石型应用会按照业务需求被拆分成多个微服务,每个服务提供特定的功能,并可能依赖于其他的微服务。每个微服务实例都可以动态部署,服务实例之间的调用通过轻量级的远程调用方式(HTTP、消息队列等)实现,它们之间通过预先定义好的接口进行访问。
由于服务实例是动态部署,每个服务实例的地址和服务信息都可能动态变化,势必需要一个中心化的组件对各个服务实例的信息进行管理,该组件管理了各个部署好的服务实例元数据,包括不仅限于服务名、IP 地址、端口号、服务描述和服务状态等。
什么是服务注册与发现?服务注册与发现主要包含两部分:服务注册与服务发现。服务注册是指服务实例启动时将自身信息注册到服务注册与发现中心,并在运行时通过心跳等方式向服务注册与发现中心汇报自身服务状态;服务发现是指服务实例向服务注册与发现中心获取其他服务实例信息,用于进行接下来的远程调用。接下来让我们介绍服务注册与发现中心的职责和服务实例进行服务注册的基本流程,以及分布式系统中数据同步的基本原理 CAP。
服务注册与发现中心有什么功能?在传统单体应用中,应用都是部署在固定的物理机器或者云平台上,他们之间的调用一般是通过固定在代码内部或者配置文件的服务地址和端口直接发起。由于应用数量较少,系统结构复杂度不高,开发人员和运维人员可以较为轻松地进行管理和配置。
随着应用架构向微服务架构迁移,服务数量的增加和动态部署动态扩展的特性,使得服务地址和端口在运行时是随时可变的。对此,我们需要一个额外的中心化组件统一管理动态部署的微服务应用的服务实例元数据,一般称它为服务注册与发现中心。服务注册与发现中心主要有以下的职责:
管理当前注册到服务注册与发现中心的微服务实例元数据信息,包括服务实例的 服务名、IP 地址、端口号、服务描述和服务状态等;
与注册到服务发现与注册中心的微服务实例维持心跳,定期检查注册表中的服务实例是否在线,并剔除无效服务实例信息;
提供服务发现能力,为服务调用方提供服务提供方的服务实例元数据。
通过服务发现与注册中心,可以很方便地管理系统中动态变化的服务实例信息。与此同时,它也可能成为系统的瓶颈和故障点。因为服务之间的调用信息来自于服务注册与发现中心,当它不可用时,服务之间的调用可能无法正常进行。因此服务发现与注册中心一般会集群化部署,提供高可用性和高稳定性。
分布式中的 CAP 理论在本质上来讲,微服务应用属于分布式系统的一种落地实践,而分布式系统最大的难点是处理各个节点之间数据状态的一致性。即使是倡导无状态的 HTTP RESTful API 请求,在处理多服务实例情况下的修改数据状态请求,也是需要通过数据库或者分布式缓存等外部系统维护数据的一致性。CAP 原理是描述分布式系统下节点数据同步的基本定理。
CAP 原理由加州大学的 Eric Brewer 教授提出,分别指 Consistency (一致性)、Availablity (可用性)、Partition tolerance (分区容忍性)。Eric Brewer 认为,以上三个指标最多同时满足两个。
Consistency,指数据一致性,表示一个系统的数据信息(包括备份数据)在同一时刻都是一致的。在分布式系统下,同一份数据可能存在于多个不同的实例中,在数据强一致性的要求下,对其中一份数据的修改必须同步到它的所有备份中。在数据同步的任何时候,都需要保证所有对该份数据的请求将返回同样的状态。
Availablity,指服务可用性,要求服务在接受到客户端请求后,都能够给出响应。服务可用性考量的是系统的可用性,要求系统在高并发情况下和部分节点宕机的情况下,系统整体依然能够响应客户端的请求。
Partition tolerance,指分区容忍性。在分布式系统中,不同节点之间是通过网络进行通信。基于网络的不可靠性,位于不同网络分区的服务节点可能会通信失败,如果系统能够容忍这种情况,说明它是满足分区容忍性的。如果系统不能够满足分区容忍性,那么将会限制分布式系统的扩展性,即服务节点的部署数量和地区都会受限,违背了分布式系统设计的初衷,所以一般来讲分布式系统都会满足分区容忍性。
在满足了分区容忍性的前提下,分布式系统并不能同时满足数据一致性和服务可用性。假设服务A现在有两个实例A1和A2,它们之间的网络通信出现了异常,基于分区容忍性,这并不会影响A1和A2独立的正常运行。假如此时客户端请求A1,请求将数据B从B1状态修改为B2,由于网络的不可用,数据B的修改并不能通知到实例A2。如果此时另一个客户端向A2请求数据B,如果A2返回数据B1,将满足服务可用性,但并不能满足数据一致性;如果A2需要等待A1的通知之后才能够返回数据B的正确状态,虽然满足了数据一致性,但并不能响应客户端请求,违背了服务可用性的指标。