摘要
最近在学习zookeeper的选举机制和使用、java如何调用及应用场景,dubbo理所应当的进入了我的视野,作为阿里开源的强大中间件dubbo,我们也应该了解其基本原理和应用场景。
RPC,远程服务调用,dubbo作为服务调用的中间人,为服务消费者和服务提供者来提供服务,首先,要知道dubbo的主要功能:
- 提供服务注册和服务发现的功能(依赖zookeeper)
- 服务间的通讯
- 实现服务间无感知调用
了解这些之后,大致理一下我们主要需要做的事:
- (由于分布式情况下,需要保持一致性)需要从zookeeper上创建、查找服务
- 制定某种通讯协议实现服务间的通讯
- 使用某种设计模式来实现服务间的无感知调用
思路理清之后,可以开始动手了。
使用技术:
- zookeeper
- netty
- jdk自带动态代理
服务注册中心:服务注册和服务发现
由于需要调用zookeeper,先搭建好zookeeper环境。
- 既然需要连接zookeeper,需要一个管理zk连接的类
/**
* @author XCXCXCXCX
* @date 2018/9/2
* @comments
*/
public enum CuratorManager {
INSTANCE;
private CuratorFramework client;
private CuratorManager(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client =
CuratorFrameworkFactory.builder()
.connectString("10.211.139.56:2181,10.211.139.56:2181,192.168.179.129:2181")
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
.build();
}
public CuratorFramework getClient(){
return CuratorManager.INSTANCE.client;
}
}
- 有了zk的连接类,可以实现一个注册中心的类了
/**
* @author XCXCXCXCX
* @date 2018/9/2
* @comments
*/
public class ServiceRegistry {
private static Logger log = LogManager.getLogger("ServiceRegistry");
private CuratorFramework client = CuratorManager.INSTANCE.getClient();
public void registerService(String serviceName,String serviceAddress){
client.start();
if(serviceName==null||serviceAddress==null){
throw new NullParamException("ServiceRegistry: serviceName and serviceAddress should not be null!");
}
String path = "/registry/" + serviceName;
try {
if(client.checkExists().forPath(path) == null){
client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path,serviceAddress.getBytes());
log.info("服务注册成功!");
}else{
client.setData().forPath(path,serviceAddress.getBytes());
log.info("服务已存在,更新成功!");
}
// System.out.println(client.getChildren().forPath(path));
// System.out.println(new String(client.getData().forPath(path)));
// Stat stat = new Stat();
// System.out.println(new String(client.getData().storingStatIn(stat).forPath(path)));
} catch (Exception e) {
e.printStackTrace();
}
}
public String discoverService(String serviceName){
client.start();
//获取服务地址
if(serviceName==null){
throw new NullParamException("ServiceRegistry: serviceName should not be null!");
}
String path = "/registry/"+serviceName;
try {
return new String(client.getData().forPath(path));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
指定通讯协议,利用netty实现异步通讯
谈到通讯,无非就是server和client,理清server和client的任务:
Server:
- 开启监听,等待client请求
- 当client请求调用服务时,查询服务是否已注册在dubbo上
- 如果存在服务,调用该服务并返回该服务调用情况
Client:
- 根据服务接口,向远程服务器发起请求
- 当请求发送成功后,等待远程服务器的响应,获取服务调用情况
Server
/**
* @author XCXCXCXCX
* @date 2018/9/2
* @comments
*/
public class Main {
public void init() {
//初始化注册中心,注册已有服务