apache-shenyu之注册中心整合与元数据同步
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了apache-shenyu之注册中心整合与元数据同步相关的知识,希望对你有一定的参考价值。
参考技术A ####### 当然通过 shenyu的disruptor应用了解到所有数据同步,实例以及元数据注册的发送,接收都使用了disruptor解耦并提高了可用性。
shenyu-register-center 作为注册中心模块,主要有三个模块需要了解
入口为ShenyuClientCommonBeanConfiguration类。通过spring.factories指定,然后初始化一个注册中心策略
ShenyuClientRegisterRepositoryFactory
可以看到我们的业务服务只要引入了apache-shenyu的pom文件,就会通过spring-boot自动注入一个ShenyuClientRegisterRepository通过如下配置类
我们只看nacos的实现
先来看位于shenyu-admin模块中的配置类
然后来看NacosClientServerRegisterRepository
上面关于业务服务的实例信息,接口元数据如何同步,通过查看其中一个nacos的实现,看到了业务服务如何通过shenyu-client如果注册到nacos,而shenyu-admin如何从nacos接收到数据
如果使用spring-boot,我们引入了对应的jar包,这里实际直接通过spring.factories & 配置方式注入
可以看到和之前client的区别,client的注入是根据配置针对性注入一个实现(当然其实也可以支持多实现,但逻辑上没有必要)也就是通过@Bean注入一个接口的实现,而数据同步的注入是分别在自己的模块通过 spring.factories & 配置注入,通过配置是可以同时存在多个数据同步方式的。
上述这些数据需要同步,如果分别是这些interface的方法入口,上述接口是抽象出来给shenyu-bootstrap使用,实现都是通过apache-shenyu的插件架构实现,而数据变化的生产者是通过DataChangedListener&DataChangedInit接口抽象在admin端进行发送,而bootstrap通过它进行订阅感知数据变化后的操作。而这些数据变化的消费者在对应数据同步的子类模块中如下
DataChangedInit 是在服务启动后初始化逻辑,没有websocket的子实现,其实就是在服务启动后的一个钩子,因为nacos,consul,etcd,zookeeper相当于都需要一个中间件服务来同步数据,需要每次启动会进行一次同步,而websocket则是直连,互相能感知到上下线,可以直接在上下线中处理
而所有数据变化的逻辑是通过spring提供的观察者机制,通过ApplicationEvent发布事件,由事件监听者来同步数据
分发事件的类为DataChangedEventDispatcher类
然后我们来看websocket关于DataChangedListener的实现
全部委托给WebsocketCollector处理
我们来看WebsocketCollector,它也是一个websocket客户端类
整合zk作为注册中心,实现更合理的rpc服务注册
前言
昨天我们对手写的rpc
框架进行了整理优化,解决了代理类和sevice
的绑定问题,自此之后我们就无需再进行手动绑定,确实方便了很多。
今天,我考虑把我们的rpc
框架服务注册中心改为zk
,至于为什么要改,原因很简单,redis
严格来说属于数据库,对于多节点数据存放确实不方便也不够灵活,但是zk
就是专门用来存储多节点数据的树形结构,不仅可以存放k-v
这样的数据,同时还有父子节点这样的数据关系,确实比redis
更灵活。
所以,我考虑把注册中心替换成zk
,当然另外一个原因是,我也想更深入的了解下zk
,而不是仅仅停留在会用的层面。之前一直有用zk
作为服务注册中心,但也一直停留在使用层面,对于其内部原理一直是一知半解,直到今天真正用注册我们之前手写的rpc
服务,踩了好多坑,才发现zk
方面确实该好好补课了。
整合zk
引入客户端依赖
开始之前,我们先要引入zk
的客户端,我引入的是一个第三方包,这个客户端是基于官方的客户端开发的,也算比较主流。
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
本来是打算直接使用官方客户端的,但是在使用的时候,发现确实不太好用,考虑到时间,最后选择了这个第三方客户端。后面有时间的话,考虑自己写一个zk
客户端,目前考虑的是基于官方的客户端实现,这也算是研究学习zk
的一种方式。
编写zk客户端工具类
然后编写zk
工具类,目前的工具类还比较简单,而且有一些问题,比如节点创建不够灵活,目前都是写死的,只能创建三层目录的节点,例如/syske-rpc-server/io.github.syske.rpc.facade.HelloService/consumer
,一部分原因是目前我对这个客户端了解的也比较少,所以也就用了一些简单的接口方法。
后面需要再优化下,考虑通过递归实现多层目录自动创建节点。
public class ZooKeeperUtil {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final String ZNODE = "/syske-rpc-server";
private static ZkClient client;
static {
client = new ZkClient(ZK_ADDRESS);
}
public static void writeData(String path, String data) {
if (!client.exists(ZNODE)){
//创建持久化节点 ,初始化数据
String[] paths = path.split("/");
client.createPersistent(ZNODE, "/" + paths[1]);
client.createPersistent(ZNODE + "/" + paths[1], "/" + paths[2]);
String chlid = client.create(ZNODE + path, data, CreateMode.PERSISTENT);
System.out.println(chlid);
}else {
//修改节点数据,并返回该节点的状态
String[] paths = path.split("/");
client.createPersistent(ZNODE + path);
Stat znodeStat = client.writeDataReturnStat(ZNODE + path, data, -1);
System.out.println(znodeStat);
}
}
public static <T> T readData(String path) {
//获取节点数据
return client.readData(ZNODE + path);
}
}
服务注册
编写服务注册工具类,这个工具类主要是用于服务注册和获取服务注册信息。
public class ServiceRegisterUtil {
public static void registerProvider(RpcRegisterEntity entity) {
ZooKeeperUtil.writeData(String.format("/%s/provider", entity.getServiceFullName()) , JSON.toJSONString(entity));
}
public static void registerConsumer(RpcRegisterEntity entity) {
ZooKeeperUtil.writeData(String.format("/%s/consumer", entity.getServiceFullName()), JSON.toJSONString(entity));
}
public static <T> T getProviderData(String path) {
return ZooKeeperUtil.readData(String.format("/%s/provider", path));
}
public static <T> T getConsumererData(String path) {
return ZooKeeperUtil.readData(String.format("/%s/consumner", path));
}
}
优化注册方式
然后把我们之前用redis
注册代码改成我们刚写的工具类即可:
服务提供者
替换注册方法
服务消费者
替换注册方法
同时还有我们动态代理远程调用部分的代码,这里只需要替换获取方法即可:
测试
然后我们分别启动服务提供者和服务消费者,看下效果,首先看下zookeeper
服务注册情况:
看了上面的注册结构是不是很熟悉呢?dubbo
的服务注册不就长这样吗?
然后我们启动消费者端远程调用下看下:
先从zk
中获取了服务的注册信息,然后远程调用,结果正常返回,是不是很简单呢?
总结
基于zk
的服务注册,我们已经完整地实现了,虽然有很多地方都需要进一步的优化,但是整体流程是ok
的,而且实际实现过程中,确实也发现了,对于zk
我以前是真的只会用,数据结构都没好好研究过,后面得好好补课了。
另外,截至目前,除了数据结构方面的优势,我并没有发现zk
作为服务注册中心的其他的优势,当然也有可能是我对zk
了解的不够深入,后面我会通过手写zk
客户端来弥补这一块知识的不足。
https://github.com/Syske/syske-rpc-server
- END -
以上是关于apache-shenyu之注册中心整合与元数据同步的主要内容,如果未能解决你的问题,请参考以下文章