您的位置:首页 > 其它

dubbo源码解析(六) dubbo服务发布过程及本地暴露

2018-03-12 23:05 696 查看
下图是dubbo服务发布过程中的日志:



从上述的日志,可以总结出dubbo服务的过程有六步:

1.暴露本地服务Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, dubbo version: 2.0.0, current host: 127.0.0.12.暴露远程服务Export dubbo service com.alibaba.dubbo.demo.DemoService to url dubbo://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280, dubbo version: 2.0.0, current host: 127.0.0.1
Register dubbo service com.alibaba.dubbo.demo.DemoService url dubbo://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280 to registry registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.0&owner=william&pid=7344®istry=zookeeper×tamp=1520861604195, dubbo version: 2.0.0, current host: 127.0.0.1
3.启动nettyStart NettyServer bind /0.0.0.0:20880, export /192.168.1.3:20880, dubbo version: 2.0.0, current host: 127.0.0.14.连接zkINFO zkclient.ZkEventThread: Starting ZkClient event thread5.向zk注册Register: dubbo://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280, dubbo version: 2.0.0, current host: 127.0.0.16.监听zkSubscribe: provider://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280, dubbo version: 2.0.0, current host: 127.0.0.1
Notify urls for subscribe url provider://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280, urls: [empty://192.168.1.3:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7344&side=provider×tamp=1520861604280], dubbo version: 2.0.0, current host: 127.0.0.1
发布服务的途径就是通过解析下面xml:<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>通过上节知识(dubbo中spring自定义schema)找到DubboNamespaceHandler这个类:



进入ServiceBean这个类



这个类继承了ApplicationListener这个接口。在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始
4000
化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进行操作。需要实现ApplicationListener接口并实现onApplicationEvent方法。把需要处理的操作放在onApplicationEvent中进行处理。
进入ServiceBean的onApplicationEvent这个方法



进入 doExportUrls





进入 doExportUrlsForProtocol



上述代码就是暴露本地服务和远程服务。暴露本地服务和远程服务区别是:
1.暴露本地服务:指暴露在用一个JVM里面,不用通过调用zk来进行远程通信。例如:在同一个服务,自己调用自己的接口,就没必要进行网络IP连接来通信。

2.暴露远程服务:指暴露给远程客户端的IP和端口号,通过网络来实现通信。
进入本地暴露 exportLocal(url)这个方法:



进入JavassistProxyFactory.getInvoker



这里使用了动态代理的方式调用了要暴露的service的方法。并且返回了Invoker对象。

Wrapper.getWrapper方法是动态生成一个代理类,其中的invokeMethod如下:public Object invokeMethod(Object o, String n, Class[] p, Object[] v)
throws java.lang.reflect.InvocationTargetException {
com.alibaba.dubbo.demo.provider.DemoServiceImpl w;
try {
w = ((com.alibaba.dubbo.demo.provider.DemoServiceImpl) $1);
} catch (Throwable e) {
throw new IllegalArgumentException(e);
}
try {
if ("sayHello".equals($2) && $3.length == 1) {
return ($w) w.sayHello((java.lang.String) $4[0]);
}
} catch (Throwable e) {
throw new java.lang.reflect.InvocationTargetException(e);
}
throw new com.alibaba.dubbo.common.bytecode.NoSuchMethodException(
"Not found method \"" + $2 + "\" in class com.alibaba.dubbo.demo.provider.DemoServiceImpl.");
}这样就执行了实际类的方法。

下面分析下Invoker这个类:



invoke 它是一个可执行的对象,能够根据方法的名称参数得到相应的执行结果,里面有一个很重要方法 Result invoke(Invocation invocation)Invocation包含了需要执行的方法和参数等重要信息。



下面分析protocol.export这个方法: private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).
getAdaptiveExtension();这个protocol对象获取就是前几节介绍的通过dubbo spi动态获取类,生成Protocol$Adpative。
进入Protocol$Adpative的export方法:



继续通过dubbo的spi,通过getExtensiion("injvm")来获取一个指定的对象,最终进入InjvmProtocol的export方法:



返回一个InjvmExporter对象,进入该类的构造函数



发现export方法的最终目的是向exporterMap赋值:
exporterMap.put(key, this)//key=com.alibaba.dubbo.demo.DemoService, this=InjvmExporter
这也就是本地服务暴露的目的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: