dubbo源码解析(六) 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 
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&timestamp=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&registry=zookeeper&timestamp=1520861604195, 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
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这个接口。在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值