dubbo 服务暴露过程源码分析

3月 15, 2018 |

dubbo 服务暴露过程的序列图如下[图片在新的窗口查看更清晰]

本文由javacoder.cn整理, 谢绝转载,谢谢
1)熟悉spring 上下文启动的同学都知道,spring会先解析xml生成BeanDefination, DubboBeanDefinitionParser的parse方法中完成dubbo 命名空间的解析。
2)在applicationContext 启动的refresh阶段会广播ApplicationEvent事件, 触发ApplicationListener.onApplicationEvent() 方法的执行, ServiceBean实现了ApplicationListener接口,所以onApplicationEvent()方法开始执行。
3)ProxyFactory$Adpative是dubbo通过Javassist字节码库动态产生的一个类, 主要功能利用dubbo的接口扩展机制适配指定的实现, 实现的代码如下[设置log4j.logger.com.alibaba.dubbo=debug 的输出,没有格式化,哈原始格式]

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {
public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws java.lang.Object {
	
if (arg2 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg2;
String extName = url.getParameter("proxy", "javassist");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
return extension.getInvoker(arg0, arg1, arg2);
}
public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {
   if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
   if (arg0.getUrl() == null) 
     throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
   com.alibaba.dubbo.common.URL url = arg0.getUrl();
   String extName = url.getParameter("proxy", "javassist");
   if(extName == null) 
     throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
    com.alibaba.dubbo.rpc.ProxyFactory extension = com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader
        .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
    return extension.getProxy(arg0);
}
}

ProxyFactory$Adpative的getInvoker()方法根据proxy 参数, 调用ExtensionLoader.getExtensionLoader()获取对应实现的ProxyFactory类,然后调用改实现的getInvoker()方法。
ProxyFactory$Adpative的getInvoker()方法类似。
4)JavassistProxyFactory.getInvoker() 实现就是反射调用指定的方法。封装成了Wrapper类
5)Protocol$Adpative 的原理同ProxyFactory$Adpative, 不再累述
6)RegistryProtocol.export 使用同样的原理,通过Protocol$Adpative 适配器,将真正的export工作代理给了DubboProtocol
7)DubboProtocol.export
核心代码参考openServer 方法, 创建dubbo 服务的监听socket 等
8)ProtocolFilterWrapper.export 将filter 加入到Invoker中
最核心的代码在buildInvokerChain方法中,为每个filter 产生一个Invoker,然后绑定到Invoker 链中。

    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class)
               .getActivateExtension(invoker.getUrl(), key, group);
		for (int i = filters.size() - 1; i >= 0; i --) {
			final Filter filter = filters.get(i);
			final Invoker<T> next = last;
			last = new Invoker<T>() {
				//删了其他非核心的代码
				public Result invoke(Invocation invocation) throws RpcException {
					return filter.invoke(next, invocation);
				}
			};
		}
        return last;
    }

9)RegistryProtocol.getRegistry 获取注册中心的实现,根据<dubbo:registry/>元素配置获取对应的RegistryFactory实现,获取Registry对象。
10)ZookeeperRegistry.register调用具体的注册中心完成服务的注册。至此服务暴露完成

Posted in: MySQL practise

Comments are closed.