源码(5)"/>
Dubbo源码(5)
文章目录
- 一.Dubbo中的动态代理
- 1.1、Dubbo Invoker领域模型
- 1.2、Invoke在RPC过程中的作用
- 二.RPC调用流程
本文主要参考自Dubbo官方文档、Dubbo项目源码以及网络文章和相关书籍,并附上自身的一些理解,如有遗漏或错误,还望海涵并指出。谢谢!
------本文基于Dubbo-2.6.1版本
一.Dubbo中的动态代理
1.1、Dubbo Invoker领域模型
在说Dubbo动态代理之前,先来看看Dubbo的Invoker领域模型。
任何框架或组件,总会有核心领域模型,比如:Spring 的 Bean,Struts 的 Action,Dubbo 的 Service,Napoli 的 Queue 等等。这个核心领域模型及其组成部分称为实体域,它代表着我们要操作的目标本身。实体域通常是线程安全的,不管是通过不变类,同步状态,或复制的方式。
服务域也就是行为域,它是组件的功能集,同时也负责实体域和会话域的生命周期管理, 比如 Spring 的 ApplicationContext,Dubbo 的 ServiceManager 等。服务域的对象通常会比较重,而且是线程安全的,并以单一实例服务于所有调用。
什么是会话?就是一次交互过程。会话中重要的概念是上下文,什么是上下文?比如我们说:“老地方见”,这里的“老地方”就是上下文信息。为什么说“老地方”对方会知道,因为我们前面定义了“老地方”的具体内容。所以说,上下文通常持有交互过程中的状态变量等。会话对象通常较轻,每次请求都重新创建实例,请求结束后销毁。
简而言之:把元信息交由实体域持有,把一次请求中的临时状态由会话域持有,由服务域贯穿整个 过程。
百度中关于领域模型的解释:
领域模型是对领域内的概念类或现实世界中对象的可视化表示。 又称概念模型、领域对象模型、分析对象模型。 它专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。
Invoker
是Dubbo 领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得Invoker渗透在整个实现代码里。而Invoker
的实现是基于动态代理的,这也是本文要讲解的重点。
1.2、Invoke在RPC过程中的作用
在整个Dubbo关于RPC通信过程的代码中出现了很多个Invoker,Invoker直译为执行器,那么这些Invoker的作用是什么呢?
下面来看一张图,简化了Dubbo RPC过程中的其他组件,来直观地看Invoker在这个过程中的作用:
可以看出,在服务提供端中,Invoker封装了具体的实现服务类。
当服务消费端需要通过RPC调用这个服务时,生成proxy调用对应的Invoker,借助网络通知到服务提供端Exporter,然后Exporter调用Invoker执行具体的服务逻辑。
可以看出,Invoker实质上就是由动态代理生成并封装了网络连接和数据处理的逻辑,以屏蔽底层的实现。这就是DUbbo动态代理技术的实际运用了。
二.RPC调用流程
在看源码之前,先来从宏观的层面了解下整个调用的流程,这里忽略了很多细节,只展示最重要的实现,如下图:
整体的流程如下:
- 客户端通过RPC调用Service接口的方法
- 通过动态代理生成一个Proxy代理对象,该对象实现了Service接口,内容大致如下:
public class proxy0 implements ClassGenerator.DC, EchoService, Service {public static Method[] methods;private InvocationHandler handlerpublic void bye(Object paramObject) {Object[] arrayOfObject = new Object[1];arrayOfObject[0] = paramObject;Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);}public String hello(String paramString){ Object[] arrayOfObject = new Object[1];arrayOfObject[0] = paramString;Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);return (String)localObject;}public Object $echo(Object paramObject) {Object[] arrayOfObject = new Object[1];arrayOfObject[0] = paramObject;Object localObject = this.handler.invoke(this, methods[2], arrayOfObject);return (Object)localObject;}public proxy0() {public proxy0(InvocationHandler paramInvocationHandler) {this.handler = paramInvocationHandler; } }
该类通过dubbo-common
模块的bytecode
模块的 Proxy类使用Javassis动态代理技术生成。
代理类首先实现了Service
接口,然后所有的重写方法调用都是集中在了InvocationHandler
的invoke
方法中执行,这里实质上就是调用了代理对象(封装了许多RPC细节)。
- 服务端接的
Protocol
收到了这个RPC调用。 Protocol
获取到被调用的Exporter
对象Exporter
对象获取到Invoker
代理对象Invoker
代理对象执行Wrapper
包装类对象中对应的方法。实质上Wrapper
对象内含有Service
实现对象,如以下代码:
public class Wrapper1 extends Wrapper implements ClassGenerator.DC
{public static String[] pns;public static Map pts;public static String[] mns;public static String[] dmns;public static Class[] mts0;public static Class[] mts1;public static Class[] mts2;public String[] getPropertyNames(){return pns;}public boolean hasProperty(String paramString){return pts.containsKey(paramString);}public Class getPropertyType(String paramString){return (Class)pts.get(paramString);}public String[] getMethodNames(){return mns;}public String[] getDeclaredMethodNames(){return dmns;}public void setPropertyValue(Object paramObject1, String paramString, Object paramObject2){ServiceImpl w;try{w = (ServiceImpl)paramObject1;}catch (Throwable localThrowable){throw new IllegalArgumentException(localThrowable);}if (paramString.equals("test01")){w.test01 = ((String)paramObject2);return;}if (paramString.equals("demoDAO")){localServiceImpl.setDemoDAO((DemoDAO)paramObject2);return;}throw new NoSuchPropertyException("Not found property \"" + paramString + "\" filed or setter method in class com.alibaba.dubbo.demo.provider.ServiceImpl.");}public Object getPropertyValue(Object paramObject, String paramString){ServiceImpl w;try{w = (ServiceImpl)paramObject;}catch (Throwable localThrowable){throw new IllegalArgumentException(localThrowable);}if (paramString.equals("test01")) {return localServiceImpl.test01;}throw new NoSuchPropertyException("Not found property \"" + paramString + "\" filed or setter method in class com.alibaba.dubbo.demo.provider.ServiceImpl.");}public Object invokeMethod(Object paramObject, String paramString, Class[] paramArrayOfClass, Object[] paramArrayOfObject)throws InvocationTargetException{ServiceImpl w;try{w = (ServiceImpl)paramObject;}catch (Throwable localThrowable1){throw new IllegalArgumentException(localThrowable1);}try{if ("hello".equals(paramString) && paramArrayOfClass.length == 1) {return w.hello((String)paramArrayOfObject[0]);}if ("bye".equals(paramString) && paramArrayOfClass.length == 1){w.bye((Object)paramArrayOfObject[0]);return null;}if ("setDemoDAO".equals(paramString) && paramArrayOfClass.length == 1){w.setDemoDAO((DemoDAO)paramArrayOfObject[0]);return null;}}catch (Throwable localThrowable2){throw new InvocationTargetException(localThrowable2);}throw new NoSuchMethodException("Not found method \"" + paramString + "\" in class com.alibaba.dubbo.demo.provider.ServiceImpl.");}
}
该包装类由dubbo-common
模块的bytecode
模块的Wrapper
类使用Javassist
动态代理技术生成。
可以看到到了这一步,其实就是在调用包装类中包装的实现类的具体方法了。
更多推荐
Dubbo源码(5)
发布评论