dubbo服务发布过程

下图是dubbo服务发布过程中的日志:

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

 

1.暴露本地服务

Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, dubbo version: 2.0.0, current host: 127.0.0.1
2.暴露远程服务

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&timestamp=1520861604280, dubbo version: 2.0.0, current host: 127.0.0.1

3.启动netty

Start NettyServer bind /0.0.0.0:20880, export /192.168.1.3:20880, dubbo version: 2.0.0, current host: 127.0.0.1

4.连接zk

INFO zkclient.ZkEventThread: Starting ZkClient event thread

5.向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.1

6.监听zk

Subscribe: 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

dubbo发布服务的途径就是通过解析下面xml:

 

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

通过dubbo中spring自定义schema找到DubboNamespaceHandler这个类:

进入ServiceBean这个类:

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

进入ServiceBean的onApplicationEvent这个方法

进入 doExportUrls

进入 doExportUrlsForProtocol

上述代码就是暴露本地服务和远程服务。暴露本地服务和远程服务区别是:

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

2.暴露远程服务:指暴露给远程客户端的IP和端口号,通过网络来实现通信。

进入本地暴露 exportLocal(url)这个方法:

进入JavassistProxyFactory.getInvoker

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

Wrapper.getWrapper方法是动态生成一个代理类,其中的invokeMethod如下:

  1. public Object invokeMethod(Object o, String n, Class[] p, Object[] v)

  2. throws java.lang.reflect.InvocationTargetException {

  3. com.alibaba.dubbo.demo.provider.DemoServiceImpl w;

  4. try {

  5. w = ((com.alibaba.dubbo.demo.provider.DemoServiceImpl) $1);

  6. catch (Throwable e) {

  7. throw new IllegalArgumentException(e);

  8. }

  9. try {

  10. if ("sayHello".equals($2) && $3.length == 1) {

  11. return ($w) w.sayHello((java.lang.String) $4[0]);

  12. }

  13. catch (Throwable e) {

  14. throw new java.lang.reflect.InvocationTargetException(e);

  15. }

  16. throw new com.alibaba.dubbo.common.bytecode.NoSuchMethodException(

  17. "Not found method \"" + $2 + "\" in class com.alibaba.dubbo.demo.provider.DemoServiceImpl.");

  18. }

这样就执行了实际类的方法。

下面分析下Invoker这个类

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

这个protocol对象获取就是前几节介绍的通过dubbo spi动态获取类,生成Protocol$Adpative。

进入Protocol$Adpative的export方法:

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

发现export方法的最终目的是向exporterMap赋值:

exporterMap.put(key, this)//key=com.alibaba.dubbo.demo.DemoService, this=InjvmExporter

这也就是本地服务暴露的目的。

posted on 2018-07-18 17:41  我&菜鸟  阅读(1008)  评论(0)    收藏  举报