概述
微服务架构下服务实例具有动态分配的网络地址,随着服务的自动扩展、故障和发布升级,导致服务实例的网络地址发生动态变更。因此,需要一种机制,支持服务消费者在服务提供者实例地址发生变更时,能够及时感知获取实例最新的地址,即服务发现机制。
服务发现的概念是随着计算机体系结构的发展而演变的旧概念。网络时代初期,不同的计算机需要相互定位,这是通过一个全球文本文件 HOSTS.TXT 完成的。因为不经常添加新主机,所以手动维护文件的地址列表。随着互联网的发展,主机的增加速度越来越快,需要一个自动化,可扩展性的更强系统,从而导致了 DNS 的发明和广泛采用。
现在,微服务架构正在推动服务发现的不断发展。随着容器化平台或云平台的不断普及,基于平台的微服务架构部署,服务的生命周期以秒和分钟来衡量。同时,因为微服务的自动扩展、故障和发布升级,导致微服务具有动态变化的地址列表,微服务的灵活性再次推动了服务发现技术的发展。现代基于容器化平台或云平台的微服务应用程序,需要解决服务地址动态变化的问题。
如上图所示,服务实例的地址动态变化,对于客户端而言,手工维护服务实例地址列表的方式已经不能满足需求,而使用服务发现模式动态更新维护服务实例地址列表是目前微服务架构下使用的必备技术。
服务发现机制角色
目前微服务的服务发现机制主要包含三个角色:服务提供者、服务消费者和服务注册表。
服务提供者(Service Provider): 服务启动时将服务信息注册到服务注册表,服务退出时将服务注册表的服务信息删除掉。
服务消费者(Service Consumer): 从服务注册表获取服务提供者的最新网络位置等服务信息,维护与服务提供者之间的通信。
服务注册表(Service Registry): 联系服务提供者和服务消费者的桥梁,维护服务提供者的最新网络位置等服务信息。
服务发现机制的关键部分是服务注册表(Service Registry)。服务注册表提供管理和查询服务注册信息的 API。当服务提供者的实例发生变更时(新增/删除服务),服务注册表需要通知服务消费者同步最新的服务实例地址列表。目前大多数的微服务框架使用 Netflix Eureka、Etcd、Consul 或 Apache Zookeeper 等作为服务注册表。
服务发现模式
为了说明服务发现模式是如何解决微服务实例地址动态变化的问题,下面介绍两种主要的服务发现模式:客户端发现模式和服务端发现模式。
客户端发现模式
使用客户端发现模式,客户端负责确定服务提供者的可用实例地址列表和负载均衡策略。客户端访问服务注册表,定时同步目标服务的实例地址列表,然后基于负载均衡算法选择目标服务的一个可用实例地址发送请求。
上图所示客户端服务发现包含自注册和客户端发现两个部分:
自注册: 服务实例调用服务注册表的注册接口进行实例地址注册。服务实例还可以提供服务运行状况检查接口,服务注册表定期访问接口检查服务实例是否健康和处理请求。服务注册表可能要求服务实例定期调用“心跳” API 以防止服务实例注册过期。
客户端发现: 当服务客户端调用目标服务时,它会查询服务注册表以获取服务实例地址列表。为了提高性能,客户端缓存服务实例地址列表。然后,服务客户端使用负载均衡算法(如循环或随机)来选择服务实例发送请求。
微保的第 2 代微服务框架(MSF)的服务发现实现就是客户端发现模式的一个例子。其中 Etcd 是一个服务注册表,它是一个强一致性键值数据存储的分布式系统,它提供了 REST APIs,用于管理服务实例注册和查询服务实例地址列表。MSF SDK 是一个微服务 SDK,它提供了服务注册功能,支持定期续租服务注册信息。它提供了服务发现功能,访问服务注册表同步并缓存目标服务的实例地址列表,支持基于负载均衡策略选择可用的目标服务并发送请求。
优点:
通常是服务客户端查询目标服务的实例地址列表之后,执行负载均衡算法选择可用的目标服务。优点是服务客户端可以灵活、智能地制定负载均衡策略,包括轮询、加权轮询、一致性哈希等策略。
可以实现点对点的网状通讯,即去中心化的通讯。可以有效避开单点造成的性能瓶颈和可靠性下降等问题。
服务客户端通常以 SDK 的方式直接引入到项目,这种方式语言的整合程度最佳,程序执行性能最佳,程序错误排查更加容易。
缺点:
服务客户端与服务注册表耦合。需要为服务客户端使用的每种编程语言和框架实现客户端服务发现逻辑。
服务客户端通常以 SDK 方式使用服务发现功能。这种侵入式方案存在于应用程序的所有客户端,如果客户端服务发现功能需要进行更新,要求所有的应用程序重新编译,部署服务。微服务的规模越大,服务更新越困难,这在一定程度上违背了微服务架构提倡的技术独立性。
服务端发现模式
使用服务端发现模式,服务客户端通过路由器(或者负载均衡器)访问目标服务。路由器负责查询服务注册表,获取目标服务实例的地址列表转发请求。
上图所示服务端服务发现包含第三方注册和服务端发现两个部分:
第三方注册: 这种方式不是服务客户端向服务注册表注册服务,而是通过一个注册处理器处理服务注册(通常是部署平台的一部分)。
服务端发现: 这种方式不是服务客户端查询服务注册表,而是发送请求给路由器(或者负载均衡器),路由器查询服务注册表获取目标服务的实例地址列表,使用负载均衡算法(如循环或随机)选择可用的服务实例转发请求。
现代容器化部署平台(如 Docker 和 Kubernetes)就是服务端服务发现模式的一个例子,这些部署平台都具有内置的服务注册表和服务发现机制。容器化部署平台为每个服务提供路由请求的能力。服务客户端向路由器(或者负载均衡器)发出请求,容器化部署平台自动将请求路由到目标服务一个可用的服务实例。因此,服务注册,服务发现和请求路由完全由容器化部署平台处理。
优点:
部署平台提供服务发现功能,负责处理服务发现的所有方面。因此,无论使用任何语言,所有的服务提供者和消费者都可以轻松地使用服务发现机制。
服务发现功能对于服务客户端而言是透明的,因此,服务发现功能的相关更新对于服务客户端是无感知的。
缺点:
部署平台的服务发现功能仅支持发现使用该平台部署的服务。例如,基于 Kubernetes 的服务发现仅适应于在 Kubernetes 上部署运行的服务。
服务的架构增加了一次转发,延迟时间会增加。整个系统增加了一个故障点,系统的运维难度增加。最关键的是负责转发请求的路由器或者负载均衡器可能变成性能的瓶颈。
微服务的一个目标是故障隔离,将整个系统切割为多个服务共同运行,如果某服务无法正常运行,只会影响到整个系统的相关部分功能,其它功能能够正常运行,即去中心化。然而,服务端发现模式实际上是集中式的做法,如果路由器或者负载均衡器无法提供服务,那么将导致整个系统瘫痪。
Service Mesh 服务发现
Service Mesh 介绍
Service Mesh 服务网格是服务于微服务应用程序的可配置基础设施层,旨在处理服务之间的大量基于网络的进程间通信。服务网络确保服务之间的通信灵活、可靠、快速和安全。服务网格提供的关键功能包括服务发现、负载平衡、加密、可观察性、可追溯性、熔断、身份验证和授权等。
服务网格通过为每个服务实例提供称为 sidecar 的代理实例来实现。Sidecars 负责处理服务间通信、监控和安全相关等所有从各个服务抽象出来的功能。这样,开发人员负责业务服务的开发、支持和维护,运营团队负责维护服务网格并运行业务服务。
客户端发现模式
服务网格提供的服务发现功能是客户端服务发现模式的一种升级实现,该功能基于 sidecar 和 pilot 实现。Sidecars,即数据面板(Data Plane),负责发现目标服务实例地址列表并转发请求。Pilots,即控制面板(Control Plane),负责管理服务注册表的所有服务注册信息。
上图所示客户端服务发现包含自注册和客户端发现两个部分:
自注册: Sidecar 实例,而不是服务本身,负责调用服务注册表的注册接口进行实例地址注册;负责定期调用“心跳” API 以续租服务实例注册信息。
客户端发现: Sidecar 实例负责与控制面板之间基于双向流式实时同步服务数据。当服务客户端发送请求时,负责转发请求的 Sidecar 实例查询本地缓存的目标服务实例地址列表,基于负载均衡算法选择一个可用的实例地址转发请求。
微保的第 3 代微服务框架的服务发现实现就是 Service Mesh 微服务架构下服务发现模式的一个例子。其中 Pilots 负责对接服务注册表,缓存所有注册的服务信息,实时感知服务注册信息的变更,更新本地缓存,实时推送变更数据给所有订阅的 Sidecars。Sidecars 负责对接服务注册表提供服务注册功能,负责对接 Pilots 提供服务发现功能。
Service Mesh微服务架构下服务发现模式是客户端发现模式的一种升级模式,它保持了常规客户端发现模式的优点,解决了客户端发现模式的缺点:
Sidecars 可以灵活、智能地制定负载均衡策略,包括轮询、加权轮询、一致性哈希等策略。实现点对点的去中心化的通讯,可以有效避开单点造成的性能瓶颈和可靠性下降问题。
通过 Sidecars,业务服务不需要关注服务注册、服务发现功能,不需要关注服务之间的通讯以及微服务治理等基本能力。通过 Pilots,服务消费者的客户端与服务注册表解耦,支持对接不同的服务注册表。两者的组合真正意义上实现了跨语言能力,解耦了业务代码和微服务基础框架,而且能够实现业务无感知的情况下升级微服务新特性。
总结
微服务架构模式下,服务实例具有动态分配的网络地址,为了满足服务客户端向服务提供者发送请求,必须使用服务发现机制。
服务发现的关键部分是服务注册表。服务注册表提供管理和查询服务注册信息的 API。可以使用 Netflix Eureka、Etcd、Consul 或 Apache Zookeeper 等服务注册表搭建服务发现基础设施。
微服务架构主要包括两种服务发现模式:客户端发现和服务端发现。客户端发现模式,客户端负责查询服务注册表,选择可用的实例地址转发请求。服务端发现模式,客户端通过路由器或者负载均衡器转发请求,路由器负责查询服务注册表,选择可用的实例地址转发请求。基于 Service Mesh 架构的服务发现模式是客户端发现模式的一种升级,它解决了客户端发现模式的缺点。
这个世界没有完美的架构和模式,不同的场景都有适合的解决方案。我们在调研决策的时候,一定要根据实际情况去权衡对比,选择最适合当前阶段的方案,然后通过渐进迭代的方式不断完善优化方案。
主流开源服务发现概览
Nacos | Eureka | Consul | CoreDNS | Zookeeper | |
---|---|---|---|---|---|
一致性协议 | CP + AP | AP | CP | — | CP |
健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | TCP/HTTP/gRPC/Cmd | — | Keep Alive |
负载均衡策略 | 权重/metadata/Selector | Ribbon | Fabio | RoundRobin | — |
雪崩保护 | 有 | 有 | 无 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 不支持 | 支持 |
访问协议 | HTTP/DNS | HTTP | HTTP/DNS | DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 不支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
跨注册中心同步 | 支持 | 不支持 | 支持 | 不支持 | 不支持 |
Spring Cloud 集成 | 支持 | 支持 | 支持 | 不支持 | 支持 |
Dubbo 集成 | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
K8S 集成 | 支持 | 不支持 | 支持 | 支持 | 不支持 |