上一章介绍了插件体系的实现,从本章开始,我们开始陆续介绍各个插件的设计与实现。之前说到了,在微服务环境下,框架默认支持的能力包括:服务发现、负载均衡、分布式链路追踪。我们先从服务发现开始,介绍框架是如何支持服务发现能力的。

一、什么是服务发现?

我们知道,将容器或者应用部署到集群时,其服务地址,即 IP端口, 是由集群系统动态分配的。那么,当我们需要访问这个服务时,如何确定它的地址呢?这时,就需要**服务发现(Service Discovery)**了。

我们可以简单把服务发现理解为从一个集群中获取到服务的访问地址,即 IP端口的过程。

二、路由方式

服务发现的路由方式,一般来说,我们有客户端路由和代理层路由两种方式。

1、客户端路由

客户端路由模式,也就是调用方负责获取被调用方的地址信息,并使用相应的负载均衡算法发起请求。调用方访问服务注册服务,获取对应的服务 IP 地址和端口,可能还包括对应的服务负载信息(负载均衡算法、服务实例权重等)。调用方通过负载均衡算法选取其中一个发起请求。如下:

img

server 启动的时候向 config server 注册自身的服务地址,server 正常退出的时候调用接口移除自身地址,通过定时心跳保证服务是否正常以及地址的有效性。

2、代理层路由

代理层路由,不是由调用方去获取被调方的地址,而是通过代理的方式,由代理去获取被调方的地址、发起调用请求。如下:

img

代理层路由这种模式,对 server 的寻址不再是由 client 去实现,而是由代理去实现。client 只是会对代理层发起简单请求,代理层去进行 server 寻址、负载均衡等。

三、技术选型

1、客户端路由还是代理层路由?

首先关于客户端路由和代理层路由的选择。假如选择代理层路由,我们需要引入一个 proxy 去做中转站,框架请求 proxy 去进行服务发现和负载均衡,这里考虑到,假如引入第三方 proxy,后续框架需要支持一些自定义实现(比如新增一种负载均衡算法)将会需要 proxy 进行相应支持,可能会产生一些不可控因素。所以这里我们选择的是客户端路由的方式。

2、CAP 定理

在进行服务发现组件选型之前·,你需要了解下 CAP 定理。

什么是 CAP 定理呢?在分布式系统中有三个重要的指标,C (即 Consistency)指的是一致性,常见的场景就是写操作之后的读操作必须返回刚刚写入的值。A(即 Availability)指的是可用性,常见的场景就是只要收到用户的请求,服务器就必须给出回应。P (即 Partition tolerance)指的是分区容错性,常见的场景就是集群之间的通信可能存在失败,分区容错性允许不同分区的服务器通信失败。

CAP 定理证明了 C、A、P 三个特性不可能同时满足,最多只能满足两种特性。具体论证大家可以去看相关论文了,这里不进行证明。

、第三方组件选择

目前社区上常见的服务发现组件基本都是保证 CP,因为 P 是不可避免的,所以在 C 和 A 的选择上,基本上都是选择 C,也就是保证数据的最终一致性,比较成熟的服务发现组件主要有 zookeeper、consul 和 etcd 等。下面我们就来调研和对比下这三种组件的区别。

zookeeper

zookeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。可以看到 zookeeper 提供的功能非常强大,假如只是打算将 zookeeper 作为服务发现类的工具,我们可能用到其配置存储和分布式同步的功能。

zookeeper 的主要优势是其成熟、健壮以及丰富的特性,然而,它也有自己的缺点,其中使用 Java 开发以及复杂性是罪魁祸首。尽管 Java 在许多方面非常伟大,然后对于这种类型的工作还是太沉重了。

etcd

etcd是一个采用http协议的分布式键值对存储系统,因其易用,简单。很多系统都采用或支持 etcd 作为服务发现的一部分,比如 kubernetes。但正是因为其只是一个存储系统,如果想要提供完整的服务发现功能,必须搭配一些第三方的工具。

consul

consul 是强一致性的数据存储。与 zookeeper 和 etcd 不一样,consul 内嵌实现了服务发现系统,所以这样就不需要构建自己的系统或使用第三方系统。这一发现系统除了上述提到的特性之外,还包括节点健康检查和运行在其上的服务。

对 zookeeper、consul、etcd 三种组件的对比,如下(来自网络)

名称优点缺点接口一致性算法
zookeeper1.功能强大,不仅仅只是服务发现 2.提供watcher机制能实时获取服务提供者的状态 3.dubbo等框架支持1.没有健康检查 2.需在服务中集成sdk,复杂度高 3.不支持多数据中心sdkPaxos
consul1.简单易用,不需要集成sdk 2.自带健康检查 3.支持多数据中心 4.提供web管理界面1.不能实时获取服务信息的变化通知http/dnsRaft
etcd1.简单易用,不需要集成sdk 2.可配置性强1.没有健康检查 2.需配合第三方工具一起完成服务发现 3.不支持多数据中心httpRaft

考虑到易用性、以及语言机制(zookeeper 是用 java 实现,consul 和 etcd 是用 go 实现),这里我们选择 consul 来进行我们框架的服务发现能力支持。

小结

本章主要介绍了服务发现的原理,路由方式(包括客户端路由和代理层路由),以及服务发现组件 zookeeper、etcd、consul 的选择。下一章我们将进行具体实现介绍