Dubbo最核心的功能包括进程协调和RPC协议通信。进程协调的关键组件是Regist,后者的关键组件在于Remoting。今天我们重点分析Dubbo的进程协调组件。
进程协调组件的职能包括:1)注册消费端组件 2)部署服务端组件 3)检测消费端和服务端的心跳 4)同步消费端的服务。其重点解决服务注册和服务发现问题,当然还有一些服务的治理功能。这也是微服务配置中心的基本核心功能。
注册组件包括的基本组件包括Registry、RegistryFactory、RegistryService和NotifyListener。其中Registry作为注册接口,其实现
Node, RegistryService,其完成注册、去注册、订阅和解除订阅等功能。
RegistryFactory通过策略模式完成Registry的调用,两者共同完成可插拔的内核模式。
NotifyListener完成通知功能。本组件的核心在于
Registry、RegistryFactory两部分,其实现的抽象类包括
AbstractRegistry和AbstractRegistryFactory。Dubbo本身自带实现Dubbo、Multicast、Redis和Zookeeper的实现,其他协议的实现需要自己实现。从可扩展的角度分析,Dubbo实现的机制非常灵活。
以Dubbo的注册为例,其完成服务的连接和监听,其具体代码如下:
public DubboRegistry(Invoker<RegistryService> registryInvoker, RegistryService registryService) {
super(registryInvoker.getUrl());
this.registryInvoker = registryInvoker;
this.registryService = registryService;
// Start reconnection timer
int reconnectPeriod = registryInvoker.getUrl().getParameter(Constants.REGISTRY_RECONNECT_PERIOD_KEY, RECONNECT_PERIOD_DEFAULT);
reconnectFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
public void run() {
// Check and connect to the registry
try {
connect(); //服务的连接
} catch (Throwable t) { // Defensive fault tolerance
logger.error("Unexpected error occur at reconnect, cause: " + t.getMessage(), t);
}
}
}, reconnectPeriod, reconnectPeriod, TimeUnit.MILLISECONDS);
}
super(registryInvoker.getUrl());
this.registryInvoker = registryInvoker;
this.registryService = registryService;
// Start reconnection timer
int reconnectPeriod = registryInvoker.getUrl().getParameter(Constants.REGISTRY_RECONNECT_PERIOD_KEY, RECONNECT_PERIOD_DEFAULT);
reconnectFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
public void run() {
// Check and connect to the registry
try {
connect(); //服务的连接
} catch (Throwable t) { // Defensive fault tolerance
logger.error("Unexpected error occur at reconnect, cause: " + t.getMessage(), t);
}
}
}, reconnectPeriod, reconnectPeriod, TimeUnit.MILLISECONDS);
}
protected final void connect() {
try {
// 判断是否启动正常,如果正常直接退出
if (isAvailable()) {
return;
}
if (logger.isInfoEnabled()) {
logger.info("Reconnect to registry " + getUrl());
}
clientLock.lock();//客户所锁定
try {
// Double check whether or not it is connected
if (isAvailable()) {
return;
}
recover();//回复服务
} finally {
clientLock.unlock();
}
} catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
if (getUrl().getParameter(Constants.CHECK_KEY, true)) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t.getMessage(), t);
}
logger.error("Failed to connect to registry " + getUrl().getAddress() + " from provider/consumer " + NetUtils.getLocalHost() + " use dubbo " + Version.getVersion() + ", cause: " + t.getMessage(), t);
}
}
try {
// 判断是否启动正常,如果正常直接退出
if (isAvailable()) {
return;
}
if (logger.isInfoEnabled()) {
logger.info("Reconnect to registry " + getUrl());
}
clientLock.lock();//客户所锁定
try {
// Double check whether or not it is connected
if (isAvailable()) {
return;
}
recover();//回复服务
} finally {
clientLock.unlock();
}
} catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
if (getUrl().getParameter(Constants.CHECK_KEY, true)) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t.getMessage(), t);
}
logger.error("Failed to connect to registry " + getUrl().getAddress() + " from provider/consumer " + NetUtils.getLocalHost() + " use dubbo " + Version.getVersion() + ", cause: " + t.getMessage(), t);
}
}
通过以上代码分析,Dubbo启动服务采用了定时线程池,并且按照固定的间隔启动,保证服务的稳定。抽象层的注册只关注于服务的引入,具体的协议层负责服务的启动注册。
通过以上的分析,注册组件分为三层,第一层为接口层,负责具体的任务职责定义;第二层为抽象注册层,负责业务的引入、销毁等生命周期管理;第三层为具体的协议注册实现层,负责具体业务的实现。Dubbo的实现是一个职责清晰,任务明确的一个过程。