@SPI("dubbo")
public interface Protocol {
/**
* 获取缺省端口,当用户没有配置端口时使用。
*
* @return 缺省端口
*/
int getDefaultPort();
/**
* 暴露远程服务:<br>
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().
* setRemoteAddress();<br>
* 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
* 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
*
* @param <T> 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
/**
* 引用远程服务:<br>
* 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端
* export()传入的Invoker对象的invoke()方法。<br>
* 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
* 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
*
* @param <T> 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
/**
* 释放协议:<br>
* 1. 取消该协议所有已经暴露和引用的服务。<br>
* 2. 释放协议所占用的所有资源,比如连接和端口。<br>
* 3. 协议在释放后,依然能暴露和引用新的服务。<br>
*/
void destroy();
}
ServiceBean都是对外提供服务,所以用的都是export
而ReferenceBean是调用服务,所以都是用refer
export
- 根据url中的export(dubbo://…)对外地址,dubbo提供服务(再启动之前,会有一些filter单性链表) doLocalExport(….)
- 获取到ZookeeperRegistry(根据协议),向zookeeper注册/dubbo/xxService/providers/地址
- 订阅重写
public <T> Exporter<T> export(final Invoker<T> originInvoker) {
//1. dubbo对外提供接口
final ExporterChangeableWrapper<T> exporter = doLocalExport(
originInvoker);
//2. 获取Registry实例
final Registry registry = getRegistry(originInvoker);
//3. 向zookeeper注册/dubbo/xxService/providers/地址
final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
registry.register(registedProviderUrl);
//4.订阅override数据
/**
provider://10.118.14.204:20890/com.test.ITestService?
category=configurators&..
**/
final URL overrideSubscribeUrl = getSubscribedOverrideUrl(
registedProviderUrl);
final OverrideListener overrideSubscribeListener = new
OverrideListener(overrideSubscribeUrl);
overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
//保证每次export都返回一个新的exporter实例
return new Exporter<T>() {
public Invoker<T> getInvoker() {
return exporter.getInvoker();
}
public void unexport() {
try {
exporter.unexport();
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
try {
registry.unregister(registedProviderUrl);
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
try {
overrideListeners.remove(overrideSubscribeUrl);
registry.unsubscribe(overrideSubscribeUrl,
overrideSubscribeListener);
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
};
}
dubbo提供对外服务接口
- 根据getProviderUrl(originInvoker) 提供者的url地址
(dubbo://10.118.14.204:20890/com.test.ITestService?…) - 并且对外提供服务protocol.export(invokerDelegete);
private <T> ExporterChangeableWrapper<T> doLocalExport(final
Invoker<T> originInvoker){
//获取到url里面的export属性:dubbo://.....
String key = getCacheKey(originInvoker);
ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>)
bounds.get(key);
if (exporter == null) {
synchronized (bounds) {
exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
//getProviderUrl是获取到url里面的export属性:dubbo://.....
final Invoker<?> invokerDelegete = new InvokerDelegete<T>
(originInvoker, getProviderUrl(originInvoker));
//protocol是dubbo协议
exporter = new ExporterChangeableWrapper<T>((Exporter<T>)
protocol.export(invokerDelegete), originInvoker);
bounds.put(key, exporter);
}
}
}
return (ExporterChangeableWrapper<T>) exporter;
}
获取Registry实例
registry://10.118.22.25:2181/com.alibaba.dubbo.registry.RegistryService?application=testservice&dubbo=2.8.4&export=dubbo://10.118.14.204:20890?com.test.ITestService?anyhost=true&application=testservice…®istry=zookeeper×tamp=1524045346142
其中registry=zookeeper
private Registry getRegistry(final Invoker<?> originInvoker){
URL registryUrl = originInvoker.getUrl();
if ("registry".equals(registryUrl.getProtocol())) {
//zookeeper
String protocol = registryUrl.getParameter("registry", "dubbo");
registryUrl = registryUrl.setProtocol(protocol).
removeParameter(Constants.REGISTRY_KEY);
}
return registryFactory.getRegistry(registryUrl);
}
refer
1.根据注册协议获取到ZookeeperRegistry
2, 组装consume的url
3. 向zookeeper中注册消费者节点/dubbo/com.test.ITestService/consumers/consumer://
4. 订阅提供者节点/dubbo/com.test.ITestService/providers
5. 根据容错机制返回对应的Invoker
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY,
Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
//根据注册协议获取到ZookeeperRegistry
Registry registry = registryFactory.getRegistry(url);
if (RegistryService.class.equals(type)) {
return proxyFactory.getInvoker((T) registry, type, url);
}
// group="a,b" or group="*" ,
Map<String, String> qs = StringUtils.parseQueryString(
url.getParameterAndDecoded(Constants.REFER_KEY));
String group = qs.get(Constants.GROUP_KEY);
if (group != null && group.length() > 0 ) {
if ( ( Constants.COMMA_SPLIT_PATTERN.split( group ) ).length > 1
|| "*".equals( group ) ) {
return doRefer( getMergeableCluster(), registry, type, url );
}
}
return doRefer(cluster, registry, type, url);
}
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry,
Class<T> type, URL url) {
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
directory.setRegistry(registry);
directory.setProtocol(protocol);
/**
组装consumer的url地址
consumer://10.118.14.229/com.test.ITestService?application=testservice
**/
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL,
NetUtils.getLocalHost(), 0, type.getName(),
directory.getUrl().getParameters());
if (! Constants.ANY_VALUE.equals(url.getServiceInterface())
&& url.getParameter(Constants.REGISTER_KEY, true)) {
/**向zookeeper中注册节点
/dubbo/com.test.ITestService/consumers/consumer://
10.118.14.229/com.test.ITestService?application=testservice&category=
consumers&check=false&default.check=false...
**/
registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY,
Constants.CONSUMERS_CATEGORY,
Constants.CHECK_KEY, String.valueOf(false)));
}
/**
订阅节点/dubbo/com.test.ITestService/providers
一旦节点发生改变,刷新本地的invoke 具体见zookeeper那一节
**/
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
return cluster.join(directory);
}
cluster
根据配置中获取cluster是failfast
MockClusterWrapper->FailfastCluster
- MockClusterWrapper
是cluster的装饰者模式,主要处理mock
public class MockClusterWrapper implements Cluster {
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return new MockClusterInvoker<T>(directory,
this.cluster.join(directory));
}
}
public class FailfastCluster implements Cluster {
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return new FailfastClusterInvoker<T>(directory);
}
}