注册中心(一)
业务痛点
项目的架构从以前的单体结构发展到现在的微服务。不仅服务的数量变的多了,而且服务都是多节点的部署。
假如在serviceA去调用serviceB,当serviceA会在配置中配置一个serviceB的ip和port进行通信。
当serviceB有10个节点的时候,我们就需要配置10个ip地址,这样做没有任何问题。
-
服务配置困难:当serviceB其中的某一个节点挂掉的时候,serviceA去调用的时候,总会发现其中一些有异常。而挂掉的节点无法serviceA无法感知到,会导致serviceA服务的一些调用也出现异常。这种也可以基于域名去做,但是服务的上线与下线每次都需要对域名进行配置。
-
服务上下线动态感知:当serviceB因为业务的增长,从10个节点扩展到12个节点,那么需要在serviceA中修改之前配置的10个ip地址。那么当serviceB被10个其他服务甚至更多的服务去调用的时候,那么这10个节点都需要进行更新。
如下图中,红色的serviceB是一个挂掉的服务,而虚线的是一个扩容的服务。
这两个问题如何解决,那么就有人去做一个注册中心的组件。
注册中心模型
注册中心的出现解决了我们的痛点。那么注册中心都会包含哪些功能呢
-
服务地址统一管理:管理所有服务的所有地址信息,设计一个key,value形式的集合存储起来。
serviceA在启动的时候,就会去注册中心去获取serviceB的通讯地址,而不用写到配置文件中了;
serviceA这个时候只需要维护注册中心的ip和port就可以,根据目标服务的名称去调用目标服务。
-
服务上下线动态感知:
通过心跳机制或者探针机制去感知服务的状态,从而维护在注册中心的节点。java中一般是通过socket(TCP)来感知。
注册中心和服务间的通信
服务和注册中心之间一定存在通信,因为要获取到调用服务的地址。
pull
拉取的方式,serviceA自己维护一个定时器,每隔N秒就会去请求一次最新的serviceB的服务节点列表,然后存储在自己的缓存中。
- 缺点
- 有延迟,在上次请求和这次请求之间会存在服务列表不一致的情况出现,最坏的场景是N秒。
- serviceA去请求注册中心会增加serviceA节点的开销,注册中心也有一定的压力。
- 优点
- 注册中心无需推送,注册中心的压力会比较小。
push
注册中心会维护一个通信通道,在serviceB节点地址列表发生变更的时候,主动去通知serviceA。
- 缺点
- 服务端需要维护通信通道,在服务节点特别多的时候,注册中心需要不断的检测通信通道是否正常(心跳包)。
- 优点
- 实时,维护一个通信通道,在注册中心地址发生变更的时候,第一时间通知到serviceA。
市面上流行的注册中心
- nacos
- redis
- etcd
- consule
- zookeeper
- eureka
注册中心对比
Nacos
数据存储:存储在内存中(ConcurrentHashMap)
通信协议:默认gRPC,支持http
心跳:自带心跳机制
数据变更推送方式:push(udp)、pull
CAP模型:支持AP和CP,默认AP
Eureka
数据存储:存储在内存中NodeDataBase(树形),持久化在文件中, 每次启动都会加载到内存中
通信协议:http
心跳:自带心跳机制
数据变更推送方式:pull(30s)
CAP模型:AP
zookeeper
数据存储:存储在内存中(ConcurrentHashMap)
通信协议:jute协议
心跳:自带心跳机制
数据变更推送方式:watch(push)
CAP模型:CP