博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SOFA 源码分析 — 泛化调用
阅读量:7111 次
发布时间:2019-06-28

本文共 2134 字,大约阅读时间需要 7 分钟。

1240

前言

通常 RPC 调用需要客户端使用服务端提供的接口,而具体的形式则是使用 jar 包,通过引用 jar 包获取接口的的具体信息,例如接口名称,方法名称,参数类型,返回值类型。

但也存在一些情况,例如客户端没有 jar 包,或者是跨语言的调用,这个时候,就需要客户端使用字符串进行泛化调用。

如何使用

还是根据官方的例子来看一下:

ConsumerConfig
consumerConfig = new ConsumerConfig
() .setInterfaceId("com.alipay.sofa.rpc.quickstart.HelloService") .setGeneric(true);GenericService testService = consumerConfig.refer();String result = (String) testService.$invoke("sayHello", new String[] { "java.lang.String" },new Object[] { "1111" });

我们看到,实际上,设置接口 ID 是和普通的调用时类似的,只是需要增加一个 Generic 属性为 true。

然后就返回了一个 GenericService 类型的代理对象,通过这个对象,就可以对服务发起调用,而调用的方式,则是使用 GenericService 的 $invoke 方法,需要传递方法名称,参数类型,参数值。并指定返回值。

SOFA 是如何实现的呢?

源码实现

既然和普通的调用只是变化了 Generic 属性,那么,我们就看看这个属性在哪些地方使用。

我们很快便找到了一个过滤器: ConsumerGenericFilter,该过滤器的生效条件则是 “客户端是否配置了泛型”。如果设置泛型,则添加到过滤链中。

而该过滤器的 invoke 方法肯定是对调用进行了一些特殊的操作,具体如下:

  1. 根据方法名称得到序列化的类型,例如普通序列化,泛型序列化,混合序列化。我们这里的例子返回的值是 0(普通序列化),然后设置序列化工厂类型,即普通序列化(根据方法名不同而不同)。
  2. 从 Request 对象中拿到方法名称,参数类型的字符串,方法参数。并重新设置到 Request 对象中,相当于重新整理了一遍。
  3. 然后根据刚刚设置的方法名重新设置调用类型。

这样就将泛型的调用修改成和普通调用一样了。

同时注意:发起调用时,该过滤器的默认 order 是 -18000,因此他会在大部分(除了异常处理和上下文)之前执行。

在使用 Bolt 的 RpcClient 进行调用的时候,会根据序列化类型决定是否进行泛型的序列化。

具体过程是,当调用时,会创建 InvokeContext 上下文,会在 Map 中存储自定义的序列化器,其中 key 是 SerializeFactoryType,value 是 0(我们这里),在 RpcRemoting 的 invokeXXX 方法中,会创建一个 RemotingCommand 对象,即执行 toRemotingCommand 方法,根据 InvokeContext 中的 SerializeFactoryType 获取到序列化工厂的枚举值,并设置到 RemotingCommand 对象中。

在 SofaRpcSerialization 类中,会根据 invokeContext 中存储的序列化枚举值得到序列化器,具体代码如下:

// 根据SerializeType信息决定序列化器boolean genericSerialize = genericSerializeRequest(invokeContext);if (genericSerialize) {    output.setSerializerFactory(genericSerializerFactory);} else {    output.setSerializerFactory(serializerFactory);}

根据SerializeType信息决定序列化器。而泛型的具体序列化器工厂则是 GenericMultipleClassLoaderSofaSerializerFactory 类,该类的会生成序列化器和反序列化器。并在 Bolt 中使用。

总结

从 SOFA 的设计中可以看出,泛化调用主要依赖于 GenericService 这个类和对应的 ConsumerGenericFilter 过滤器,如果一个客户端设置泛化了,那么调用过程中则会启用这个过滤器。

这个过滤器会将请求的数据重新整理。并修改成普通调用的样子。

同时也会设置一个泛型调用的序列化枚举放置在上下文中,上下文在 Bolt 中会根据枚举值动态获取不同的序列化器和反序列化器,对输出参数和返回值经进行处理。

转载于:https://www.cnblogs.com/stateis0/p/9007591.html

你可能感兴趣的文章
Android应用截图嵌入到真实设备
查看>>
easyui menu 添加hideItem/showItem 方法
查看>>
查看WEB ADI所对应的包过程函数
查看>>
附12 grafana配置文件
查看>>
第六十九节,css入门基础
查看>>
C++析构函数定义为虚函数(转载)
查看>>
打印数字回环
查看>>
berkeley db储存URL队列的简单实现增、删、查
查看>>
使用 jstack 查询线程死锁错误日志 定位问题
查看>>
python3根据地址批量获取百度地图经纬度
查看>>
TCP/IP协议族之运输层(TCP流量控制和拥塞控制 [2])
查看>>
WPF 异步执行
查看>>
Redis简单示例
查看>>
BZOJ 2229 最小割
查看>>
BZOJ 3546 Life of the Party (二分图匹配-最大流)
查看>>
Switch Between Gnome And KDE Desktops In Ubuntu Or Kubuntu
查看>>
VIM Quick Reference Card
查看>>
VS2010总报错:是否缺少程序集引用?
查看>>
计算机十二种常用密码破解法
查看>>
编程算法 - 最长公共子序列(LCS) 代码(C)
查看>>