Dubbo源码解析(十九)Dubbo 泛化引用
泛化引用的一个例子
public static void main(String[] args) throws InterruptedException {
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName("generic-reference-app");
// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper:2181");
registry.setProtocol("zookeeper");
registry.setClient("zkclient");
// 引用远程服务
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setInterface("com.wuhulala.dubbo.user.service.MyGenericService");
reference.setApplication(application);
reference.setRegistry(registry);
//reference.setVersion("1.0.0");
reference.setRetries(0);
reference.setGeneric(true);
GenericService genericService = reference.get();
Object result = genericService.$invoke("sayHello", new String[]{ "java.lang.String"}, new Object[]{ "world"});
System.out.println("==========================");
System.out.println(result);
System.out.println("==========================");
Thread.sleep(100000);
}
- 先把消费者注册到注册中心,并且这个已经被改变为和正常注册的消费者了
consumer://10.0.75.1/com.alibaba.dubbo.rpc.service.GenericService?application=generic-reference-app&category=consumers&check=false&dubbo=2.5.3&generic=true&interface=com.wuhulala.dubbo.user.service.MyGenericService&pid=20744&retries=0&side=consumer×tamp=1542551437436
==>
/dubbo/com.wuhulala.dubbo.user.service.MyGenericService/consumers/consumer%3A%2F%2F10.0.75.1%2Fcom.alibaba.dubbo.rpc.service.GenericService%3Fapplication%3Dgeneric-reference-app%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.5.3%26generic%3Dtrue%26interface%3Dcom.wuhulala.dubbo.user.service.MyGenericService%26pid%3D20744%26retries%3D0%26side%3Dconsumer%26timestamp%3D1542551437436
经过toCategoryPath 转换为如下
其中的获取服务的代码如下
public String getServiceInterface() {
return getParameter(Constants.INTERFACE_KEY, path);
}
类别是consumers
可以看到本来生成的第一段里面的interface就是一开始有Refrence生成的url的。
这一段的toUrlPath
的目的是为了找到需要注册在zookeeper的节点。
所以泛型调用最终的注册到注册中心的地址还是在对应的服务上
节点的数据就是Refrence刚才生成的那段url的罢了
然后客户端在调用的时候再和服务端建立连接,进行远程调用。
那么以上的流程在客户端是如何实现的呢?
那么就要看看客户端的GenericFilter
了
GenericImplFilter#invoke
// 如果是泛化引用
if (ProtocolUtils.isGeneric(generic)
&& (!$INVOKE.equals(invocation.getMethodName()) && !$INVOKE_ASYNC.equals(invocation.getMethodName()))
&& invocation instanceof RpcInvocation) {
RpcInvocation invocation2 = new RpcInvocation(invocation);
String methodName = invocation2.getMethodName();
Class<?>[] parameterTypes = invocation2.getParameterTypes();
Object[] arguments = invocation2.getArguments();
String[] types = new String[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
types[i] = ReflectUtils.getName(parameterTypes[i]);
}
Object[] args;
// 如果指定了序列化方式
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
args = new Object[arguments.length];
// 序列化
for (int i = 0; i < arguments.length; i++) {
args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD);
}
} else {
// 使用默认序列化方式
args = PojoUtils.generalize(arguments);
}
// 如果是需要返回的,设置MethodName
if (RpcUtils.isReturnTypeFuture(invocation)) {
invocation2.setMethodName($INVOKE_ASYNC);
} else {
invocation2.setMethodName($INVOKE);
}
invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
invocation2.setArguments(new Object[]{ methodName, types, args});
return invoker.invoke(invocation2);
}
可以看到这里,主要做了以下几步的事情
- 如果是泛化引用,首先进行拆包,获取方法名称、参数类型、参数值
- 把参数序列化
- 执行
还没有评论,来说两句吧...