从源码看zookeeper注册中心的实现
2020/3/9 8:02:12
本文主要是介绍从源码看zookeeper注册中心的实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
motan中的注册中心
注册中心是在很多RPC框架中不可缺少的一部分,最近公司需要将现有系统进行升级,也需要一套注册中心进行对多个执行器进行管理。 今天就先学习一下在开源框架中是如何进行使用的,主要关注zookeeper的实现。
motan 中的consumer和provider
provider作为服务的提供者,在发布后会将自己提供服务的信息、机器IP、端口注册到zk中。 consumer在调用具体服务的时候,会先根据调用服务的信息,去注册中心查询到当前服务被暴露在哪些机器上。然后返回需要的代理类,最 终在通过客户端的负载均衡和高可用的策略进行调用。 我们可以运行motan-demo中的MotanApiExportDemo,然后观察zookeeper,主要代码如下: //2-设置接口及实现类 motanDemoService.setInterface(MotanDemoService.class); motanDemoService.setRef(new MotanDemoServiceImpl()); // 配置服务的group以及版本号 motanDemoService.setGroup("motan-demo-rpc"); motanDemoService.setVersion("1.0"); //3-配置注册中心zk RegistryConfig registry = new RegistryConfig(); registry.setRegProtocol("zookeeper"); registry.setAddress("192.168.88.129:2181"); motanDemoService.setRegistry(registry); ...... motanDemoService.setExport("motan:8004"); 会发现zk下面会多出一个目录 motan 继续看看里面的内容吧: ls /motan [motan-demo-rpc] ls /motan/motan-demo-rpc [com.weibo.motan.demo.service.MotanDemoService] ls /motan/motan-demo-rpc/com.weibo.motan.demo.service.MotanDemoService [server,unavailableServer] ls /motan/motan-demo-rpc/com.weibo.motan.demo.service.MotanDemoService/server [10.45.176.187:8002] 到这里我们大体就了解了provider在注册中心中注册了哪些内容: group+接口类的全名称。 下面我们通过源码来主要看一下客户端是怎么获取所需要调用的服务地址的吧。
深入源码
终于可以看代码了! 直接来到关键点ClusterSupport.init() //这里是进行服务的订阅,通过zk的watch机制,当服务发生变化,会调用ClusterSupport里面的notify方法进行刷新集群信息 Registry registry = getRegistry(ru); registry.subscribe(subUrl, this); 这里的subUrl其实就是: motan://10.45.176.187:0/com.weibo.motan.demo.service.MotanDemoService?group=motan-demo-rpc 然后会走到CommandFailbackRegistry类中: @Override protected void doSubscribe(URL url, final NotifyListener listener) { LoggerUtil.info("CommandFailbackRegistry subscribe. url: " + url.toSimpleString()); URL urlCopy = url.createCopy(); CommandServiceManager manager = getCommandServiceManager(urlCopy); manager.addNotifyListener(listener); subscribeService(urlCopy, manager); subscribeCommand(urlCopy, manager); List<URL> urls = doDiscover(urlCopy); if (urls != null && urls.size() > 0) { this.notify(urlCopy, listener, urls); } } 重点关注subscribeService方法,当选择zookeeper实现的注册中心时,会进入ZookeeperRegistry类的subscribeService方法: String serverTypePath=ZkUtils.toNodeTypePath(url,ZkNodeType.AVAILABLE_SERVER); zkClient.subscribeChildChanges(serverTypePath, zkChildListener); 此时的serverTypePath: /motan/motan-demo-rpc/com.weibo.motan.demo.service.MotanDemoService/server 这不就是provider在注册中心注册的地址吗。 到这里我们就知道了consumer是如何获取服务所在地址的了。 当服务数量发生变化时候,consumer是怎么感知的呢? 看一下在上面方法的subscribeChildChanges 中传入了zkChildListener就了解了: childChangeListeners.putIfAbsent(serviceListener, new IZkChildListener() { //对父节点添加监听子节点变化。 @Override public void handleChildChange(String parentPath, List<String> currentChilds) { System.out.println("服务有变化!!!!!!!!!!"); serviceListener.notifyService(url, getUrl(), nodeChildsToUrls(url, parentPath, currentChilds)); LoggerUtil.info(String.format("[ZookeeperRegistry] service list change: path=%s, currentChilds=%s", parentPath, currentChilds.toString())); } }); 这里consumer对serverTypePath进行了监听,如下下面的临时节点有变化就会回调当前的IZkChildListener。 那又是怎么通知给consumer的? serviceListener.notifyService: for (NotifyListener notifyListener : notifySet) { notifyListener.notify(registry.getUrl(), finalResult); } 我们只需要找到notifyListener是从哪里来的就可以。在上面的 CommandFailbackRegistry.doSubscribe中有这样一段代码: manager.addNotifyListener(listener); notifyListener就是从这里加入的。 而这个listener就是consumer在订阅服务列表时候进行加入的,发现又回到了最开始 ClusterSupport.init()中 registry.subscribe(subUrl, this); 看一下ClusterSupport就明白了: ClusterSupport<T> implements NotifyListener notify方法就在ClusterSupport类中: public synchronized void notify(URL registryUrl, List<URL> urls) ...... 具体代码就不列出了,只要知道这里的urls就是服务列表发生变化时候,回调IZkChildListenerz监听器所获取的所有server的列表。 拿到这个列表就可以刷新之前缓存的server列表了。 然后再继续交给后面的负载均衡loadbalance进行选择一个合适的server地址进行服务的调用。 //刷新最新的服务到cluster refreshCluster();
总结
作为注册中心ZooKeeper的数据模型简单,就是一棵树.并且拥有Watcher机制,让我们方便的去满足服务订阅的需求。学习了其motan中的使用,相信参考其思路一定可以在自己的项目中来实现一套。 注册中心还有很多种实现,后续会继续学习使用,并且进行比较。
点击查看更多内容
这篇关于从源码看zookeeper注册中心的实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求
- 2024-10-01使用 golang 将ETH账户的资产平均分散到其他账户
- 2024-10-01JWT用户校验课程:从入门到实践
- 2024-10-01Server Component课程入门指南
- 2024-09-30Dnd-Kit学习:新手快速入门指南