Skip to content

04服务治理:如何正确理解服务治理解决方案?

在微服务架构中,服务治理可以说是最为关键的一个要素。我们在上一课时介绍案例分析时 ,就提到各个微服务需要通过服务治理实现自动化的服务注册发现机制。在本课程中,我们将基于 Spring Cloud 中的 Spring Cloud Netflix Eureka 来构建服务治理组件,但业界关于服务治理的实现工具并不只限于这一款。因此,为了更好地理解服务治理背后的基本需求、设计模型以及相应的实现策略和工具,做到触类旁通,我们需要首先对服务治理的解决方案做全面阐述。

如何理解服务治理的基本需求?

在微服务架构中,对于任何一个服务而言,既可以是服务提供者,也可以是服务消费者。围绕服务消费者如何调用服务提供者这个问题,需要进行服务的治理

对于服务治理 而言,可以说支持服务注册和服务发现就是它最基本也最重要的功能需求。这个需求的来源本质上是微服务系统中复杂的服务实例状态变化。相较传统的 RPC 架构,在支持云原生的微服务架构中,首当其冲面临的一大挑战就是服务实例的数量较多,而这些服务自身对外暴露的访问地址也具有动态性。而且,由于自动扩容、服务的失败和更新等因素,服务实例的运行时状态也经常变化,如下图所示:

服务实例管理中的动态性

这样一来,对于服务提供者而言,就需要一个机制能够将自己的服务实例注册到服务注册中心 ,我们希望这个过程是自动化的而不是手工静态指定的。另一方面,对于服务消费者而言,我们也希望它能自动发现这些服务实例并进行远程调用。当服务实例的运行状态发生变化时,注册中心需要确保这些状态变更都能得到有效的维护和传递。

除了服务注册和发现之外,对于注册中心而言,我们还需要其具备高可用。因为为了确保服务高可用性,也需要注册中心本身不能宕机。通过构建集群机制,服务只要连接集群中的任何一台注册中心服务器完成服务注册和发现即可,单台服务器的宕机不影响服务调用的正常进行。本课程将要介绍的 Eureka 就具备这种对等集群的构建能力,我们会在下一课时中进行详细介绍。

在使用上,注册中心是一种服务器组件,而服务的提供者和消费者都是注册中心的客户端。这些客户端和注册中心之间需要进行交互,由于涉及服务的注册和发现、服务访问中的负载均衡等机制,需要确保交互过程简单而高效。同时,考虑到异构系统之间的交互需求,注册中心作为一种平台化解决方案也应该提供多种客户端技术的集成支持。这也是我们对比各个注册中心实现方案的考虑点之一。

如何理解服务治理的设计模型?

访问注册中心的客户端程序一般会嵌入在服务提供者和服务消费者内部。在服务启动时,服务提供者通过内部的注册中心客户端程序自动将自身注册到注册中心,而服务消费者的注册中心客户端程序则可以从注册中心中获取那些已经注册的服务实例信息。注册中心的基本模型参考下图:

注册中心客户端与注册中心交互示意图

同时,为了提高服务路由的效率和容错性,服务消费者可以配备缓存机制以加速服务路由。更重要的是,当服务注册中心不可用时,服务消费者可以利用本地缓存路由实现对现有服务的可靠调用。上图中也展示了这一设计思路。

如何理解服务治理的实现策略?

基于前面的讨论内容,我们可以得知,对于服务治理工具而言,在实现上的主要难度在于在服务提供者实例状态发生变更时如何同步到服务的消费者。

从架构设计上讲,状态变更管理可以采用发布-订阅模式,体现在服务提供者可以根据服务定义发布服务,而服务消费者则通过对自己感兴趣的服务进行订阅并获取包括服务地址在内的各项元数据。发布-订阅功能还体现在状态变更推送,即当注册中心服务定义发生变化时,主动推送变更到该服务的消费者。

基于发布-订阅设计思想,就诞生了一种服务监听机制。服务监听机制确保服务消费者能够实时监控服务更新状态,是一种被动接收变更通知的实现方案,通常采用监听器以及回调机制,如下图所示。

服务监听机制效果图

我们假定以一种分层结构来展示注册中心的内部组成,可以看到这里有三个服务,每个服务有两个实例节点。服务消费者可以对这些具体的服务定义节点添加监听器,当这些节点发生变化时(例如图中服务 A 的第二个实例变得不可用),注册中心就能触发监听器中的回调函数确保更新通知到每一个服务消费者。显然,使用监听和通知机制具备实时的数据同步效果。

另外一种确保状态信息同步的方式是采用轮询机制。轮询机制是一种主动拉取策略,即服务的消费者定期调用注册中心提供的服务获取接口获取最新的服务列表并更新本地缓存,如下图所示:

服务轮询机制效果图

轮询机制实现上就是一个定时程序,需要考虑定时的频率以确保数据同步的时效性

如何理解服务治理的实现工具?

目前市面上存在一批主流的服务治理实现工具 ,包括常见的 Consul 、ZooKeeper、Netflix Eureka 等,这些实现工具采用独立不同的实现策略。其中 Consul 来自 HashiCorp 公司,是一款用来实现分布式环境下服务发现与配置的开源工具。而 ZooKeeper 是 Apache 顶级项目,作为分布式协调领域的代表性框架被广泛用于注册中心、配置中心、分布式锁等的构建场景。而 Netflix Eureka 则采用了一套完全不同的实现方案,在本课程中会对其进行详细地讨论。

以 ZooKeeper 为例,它就是"服务监听机制"实现策略的典型代表性工具。ZooKeeper 本质上是一个树形结构,可以在树上创建临时节点,并对节点添加监听器。临时节点的客户端关注该节点的状态,一旦发生变化则通过监听器回传消息到客户端,然后客户端的回调函数就会得到调用。在 Dubbo 中就使用了 ZooKeeper 作为它的默认注册中心实现机制。

基于 ZooKeeper 的监听机制示意图

而对于本课程将要介绍的 Netflix Eureka 而言,采用的就是典型的"轮询机制"来实现服务实例状态的同步,默认的同步频率是 30 秒。

如何理解服务治理与负载均衡之间的关系?

现在,我们来关注服务治理的另一个话题,我们知道对于服务注册而言,一般都是将服务自身的实例信息实时同步到注册中心即可。而关于服务发现环节,业界也有两种不同的实现方式,**一种是客户端发现机制,一种则是服务器端发现机制。**在微服务架构中,主流的是采用客户端发现机制,即在每个服务消费者内部保存着一个服务列表:

客户端发现机制示意图

当服务消费者真正对某一个服务提供者发起远程调用时,就需要决定具体的服务提供者实例,这时候就需要集成负载均衡机制。同样,这时候的负载均衡也是一种客户端行为,被称为客户端负载均衡:

客户端负载均衡示意图

如何理解Spring Cloud中的服务治理解决方案?

此外,Spring Cloud 中提供了对微服务架构中服务治理工作的强大支持,其整体服务治理方案如下图所示:

Spring Cloud 中的服务治理解决方案图

上图中,我们已经在前面的内容提到了Netflix Eureka ,该工具采用自身特有的一套实现机制,且客户端和服务器端都是采用 Java 实现,一方面可以用于基于 JVM 的开发环境。另一方面,因为与 Eureka 服务器端的交互方式是通过基于 HTTP 协议的 RESTful API,所以也可以将那些由其他语言开发的但能提供 HTTP 端点的异构微服务纳入服务治理体系中来。Spring Cloud Netflix Eureka 基于 Netflix Eureka 并做了一定的封装。

另一方面,Spring Cloud Netflix 中也集成了Netflix Ribbon 组件来实现客户端负载均衡。 Netflix Ribbon 组件会从 Eureka 服务器中获取所有注册服务的服务列表。一旦获取服务列表,Ribbon 就能通过各种负载均衡策略实现服务调用。Spring Cloud Netflix Ribbon 在 Ribbon的基础上封装了多种使用方式,并能与 RestTemplate 完成无缝的整合。

包括 Eureka 和 Ribbon 二者内容的 Spring Cloud Netflix 是 Spring Cloud 中较早支持的微服务开发套件。而在 Spring Cloud 的后续发展过程中,关于如何构建注册中心实现上存在多款可供选择的技术方案,包括前面介绍到的 Consul 和 ZooKeeper。关于这两款工具的介绍不是课程的重点,你可以参考相关资料做进一步学习。

小结

服务治理是微服务架构区别普通分布式系统的核心技术体系,今天我们围绕这一主题抛出了一系列问题并对这些问题进行一一解答。业界关于服务治理的设计模型、实现策略以及对应的实现工具都有多种表现形态,我们综合梳理了这些知识点,并给出了 Spring Cloud 中的服务治理解决方案。

这里给大家留一道思考题:服务治理的实现策略主要分成哪两种?

本课程将围绕 Spring Cloud Netflix Eureka 来实现服务治理功能,下一课时中我们就将进入到关于 Eureka 的介绍环节,先来看如何构建 Eureka 服务器并理解 Eureka 服务器端组件的实现原理。