一、服务注册中心
对于服务提供者,它需要发布服务;由于应用系统的复杂性,服务的数量、类型不断膨胀;对于服务消费者,它最关心的是如何获取到它所需要的服务。对于服务提供方和消费方来说,它们还有可能兼具这两种角色;既需要提供服务,又需要消费服务。
如何有效地管理服务订阅/发布,避免硬编码地址信息是分布式服务框架需要解决的一个问题。通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理,服务注册中心就是专门用来管理服务订阅/发布的配置管理节点。
二、几个概念
1. 服务提供者
服务提供者是发布服务的服务提供方,它通常就是一个普通的Java实现类。
2. 服务消费者
服务消费者是调用远程服务的消费方,它可能是个简单的客户端、Web前台,也可能嵌套在某个服务的内部。消费者的配置示例如下:
3. 服务注册中心
服务注册中心是分布式服务框架的目录服务器,相比于传统的目录服务器,它有如下几个特点:
HA:支持数据持久化、支持集群 数据一致性问题:集群中所有的客户端应用看到同一份数据,不能出现读或者写数据不一致 数据变更主动推送:当注册中心的数据发生变更时需要能够及时将变化的数据通知给客户端
三、关键功能特性设计
工作原理图示:
![6ad89f0c199f548dd413b355cc2f9701.png](https://i-blog.csdnimg.cn/blog_migrate/8f76039b10eaefa0c7ee018aa2a2b9a7.jpeg)
角色 说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次调和调用时间的监控中心
Container 服务运行容器
说明:
1. 服务提供者在启动时,根据服务发布文件中配置的服务发布信息向注册中心注册自己提供的服务
2. 服务消费者在启动时,根据消费者配置文件中配置的服务消费信息向注册中心订阅自己所需的服务,消费者刷新本地缓存的路由表
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心主动推送变更数据给消费者,消费者刷新本地缓存的路由表
4. 服务消费者从本地缓存的服务提供者地址列表中,基于负载均衡算法选择一台服务提供者进行调用。
1. 支持对等集群
服务注册中心需要支持对等集群,其中一个或多个服务注册中心进程宕机,不会导致服务注册中心集群功能不可用
对于客户端,无论注册中心集群配置多少个进程,客户端只需要连接其中某一个即可
2. 提供CRUD接口
3. 安全加固
服务注册中心需要进行安全加固,安全加固主要涉及两部分:
链路的安全性 数据的安全性
链路的安全性指的是服务注册中心对客户端连接进行安全认证,认证策略非常多,最简单的就是基于IP地址的黑名单校验,更加复杂的有基于用户名+密码的认证,或者基于密钥+数字证书的认证。
认证失败,则关闭链路,拒绝客户端连接。
数据的安全性主要针对服务注册中心的数据进行权限控制:
非授权客户端既不能读也不能写 普通运维人员只能读,不能修改 管理员既可以读也可以修改 不同的服务目录可以设置不同的访问权限,例如消费者只能查看它所在机房的服务
4. 订阅发布机制
服务注册中心需要支持服务的订阅发布,对于服务提供者,可以根据服务名等信息动态发布服务;对于消费者,可以根据订阅关系主动获得服务发布者的地址信息等 。
订阅发布机制还且个比较重要的机制就是对变化的监听有主动推送的能力。
5. 可靠性
四、 基于ZooKeeper的服务注册中心设计
1. 服务订阅发布流程设计
第一步:ZooKeeper客户端通过创建org.apache.zookeeper.ZooKeeper的一个实例对象连接ZooKeeper服务器,然后调用这个类提供的接口来和服务器交互
第二步:根据服务提供者发布的服务列表,循环调用create(String path,byte[] data,List acl,createMode)接口,创建目录节点,同时将服务属性定稿目录节点的内容中。create方法用于创建一个给定路径的目录节点,并给它设置数据。
第三步:与第一步相同
第四步:消费者根据消费的服务名,从ZooKeeper Server的服务发布目录中查询已经发布的服务地址和属性信息。getData(String path,boolean watch,Stat stat)方法用于获取这个path对应的目录节点存储的数据,数据的版本等信息可以通过stat来指定,同时还可以设置是否监控这个目录节点数据的状态。获得服务提供者信息之后,将其更新到本地缓存中,避免每次服务调用都要实时去ZooKeeper Server查询。
第五步:消费者监听服务提供者目录列表,当有服务上下线时,可以获取ZooKeeper Server的通知消息。
第六步:服务提供者调用 create(String path,byte[] data,List acl,CreateMode cretaeMode)方法动态注册新的服务
第七步:消费者通过监听器Watcher的process(WatchedEvent event)方法获取变更的路径信息,然后调用 getData(String path,boolean watch,Stat stat)接口获取变更的数据,最后更新本地缓存的服务路由表。
第八步:服务提供者取消已发布的服务,调用delete(String path,int version)方法删除path对应的目录节点,version为-1可以匹配任何版本,也就删除了这个目录节点的所有数据。
第九步:消费者接收到变更通知推送消息后,根据删除的路径获取删除的具体服务信息;更新缓存的服务路由表,将已经下线的服务从路由表中删除
第十步:ZK客户端与服务器的连接会话终止,存储在ZK上的所有临时数据与注册的订阅者都被自动移除
第十一步:消费者获取服务列表被删除的通知消息后,更新本地缓存的路由表,将发生会话超时的服务提供者从路由表中清除掉
实际项目中,消费者与服务提供者的启动顺序是无法控制的。
2. 服务健康状态检测
基于ZK客户端和服务端的长连接和会话超时控制机制,可以非常方便 地实现服务健康状态检测。
3. 对等集群防止单点故障
4. 变更通知机制
服务提供者将服务注册消息保存在ZooKeeper的某个服务目录节点中,消费者监控服务配置信息的状态,一旦配置信息发生变化,集群中的每个消费者实例就会收到ZooKeeper通知,然后从ZooKeeperServer获取新的服务注册信息应用到系统中。
五、dubbo服务注册中心
![a7531548fb8c2ff0b4a0e7cb8462f548.png](https://i-blog.csdnimg.cn/blog_migrate/243517faeb275805e318492ccebf9cc2.jpeg)
/dubbo:这是dubbo在ZooKeeper上创建的根节点; /dubbo/com.foo.BarService:这是服务节点,代表了Dubbo的一个服务; /dubbo/com.foo.BarService/providers:这是服务提供者的根节点,其子节点代表了每一个服务真正的提供者;
注册中心的工作流程
1)服务提供方启动
服务提供者在启动的时候,会在ZooKeeper上注册服务。所谓注册服务,其实就是在ZooKeeper的/dubbo/com.foo.BarService/providers节点下创建一个子节点,并写入自己的URL地址,这就代表了com.foo.BarService这个服务的一个提供者。
2)服务消费者启动
服务消费者在启动的时候,会向ZooKeeper注册中心订阅自己的服务。其实,就是读取并订阅ZooKeeper上/dubbo/com.foo.BarService/providers节点下的所有子节点,并解析出所有提供者的URL地址来作为该服务地址列表。
同时,服务消费者还会在ZooKeeper的/dubbo/com.foo.BarService/consumers节点下创建一个临时节点,并写入自己的URL地址,这就代表了com.foo.BarService这个服务的一个消费者。
3)消费者远程调用提供者
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一个提供者进行调用,如果调用失败,再选另一个提供者调用。
4)增加服务提供者
增加提供者,也就是在providers下面新建子节点。一旦服务提供方有变动,zookeeper就会把最新的服务列表推送给消费者。
5)减少服务提供者
所有提供者在ZooKeeper上创建的节点都是临时节点,利用的是临时节点的生命周期和客户端会话相关的特性,因此一旦提供者所在的机器出现故障导致该提供者无法对外提供服务时,该临时节点就会自动从ZooKeeper上删除,同样,zookeeper会把最新的服务列表推送给消费者。
6)ZooKeeper宕机之后
消费者每次调用服务提供方是不经过ZooKeeper的,消费者只是从zookeeper那里获取服务提供方地址列表。所以当zookeeper宕机之后,不会影响消费者调用服务提供者,影响的是zookeeper宕机之后如果提供者有变动,增加或者减少,无法把最新的服务提供者地址列表推送给消费者,所以消费者感知不到。
专注于技术热点大数据,人工智能,JAVA、Python、 C 、GO、Javascript等语言最新前言技术,及业务痛点问题分析,请关注【编程我最懂】共同交流学习。