SOFA 源码分析 — 泛化调用

前言
通常 RPC 调用需要客户端使用服务端提供的接口,而具体的形式则是使用 jar 包,通过引用 jar 包获取接口的的具体信息,例如接口名称,方法名称,参数类型,返回值类型。
但也存在一些情况,例如客户端没有 jar 包,或者是跨语言的调用,这个时候,就需要客户端使用字符串进行泛化调用。
如何使用
还是根据官方的例子来看一下:
ConsumerConfig<GenericService> consumerConfig = new ConsumerConfig<GenericService>()
.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 方法肯定是对调用进行了一些特殊的操作,具体如下:
- 根据方法名称得到序列化的类型,例如普通序列化,泛型序列化,混合序列化。我们这里的例子返回的值是 0(普通序列化),然后设置序列化工厂类型,即普通序列化(根据方法名不同而不同)。
- 从 Request 对象中拿到方法名称,参数类型的字符串,方法参数。并重新设置到 Request 对象中,相当于重新整理了一遍。
- 然后根据刚刚设置的方法名重新设置调用类型。
这样就将泛型的调用修改成和普通调用一样了。
同时注意:发起调用时,该过滤器的默认 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 中会根据枚举值动态获取不同的序列化器和反序列化器,对输出参数和返回值经进行处理。
SOFA 源码分析 — 泛化调用的更多相关文章
- SOFA 源码分析 —— 服务引用过程
前言 在前面的 SOFA 源码分析 -- 服务发布过程 文章中,我们分析了 SOFA 的服务发布过程,一个完整的 RPC 除了发布服务,当然还需要引用服务. So,今天就一起来看看 SOFA 是如何引 ...
- Dubbo 源码分析 - 服务调用过程
注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...
- SOFA 源码分析 — 调用方式
前言 SOFARPC 提供了多种调用方式满足不同的场景. 例如,同步阻塞调用:异步 future 调用,Callback 回调调用,Oneway 调用. 每种调用模式都有对应的场景.类似于单进程中的调 ...
- SOFA 源码分析 — 自动故障剔除
前言 集群中通常一个服务有多个服务提供者.其中部分服务提供者可能由于网络,配置,长时间 fullgc ,线程池满,硬件故障等导致长连接还存活但是程序已经无法正常响应.单机故障剔除功能会将这部分异常的服 ...
- SOFA 源码分析 — 负载均衡和一致性 Hash
前言 SOFA 内置负载均衡,支持 5 种负载均衡算法,随机(默认算法),本地优先,轮询算法,一致性 hash,按权重负载轮询(不推荐,已被标注废弃). 一起看看他们的实现(重点还是一致性 hash) ...
- SOFA 源码分析 — 预热权重
前言 SOFA-RPC 支持根据权重对服务进行预热功能,具体地址:预热权重. 引用官方文档: 预热权重功能让客户端机器能够根据服务端的相应权重进行流量的分发.该功能也常被用于集群内少数机器的启动场景. ...
- SOFA 源码分析— 事件总线
前言 大部分框架都是事件订阅功能,即观察者模式,或者叫事件机制.通过订阅某个事件,当触发事件时,回调某个方法.该功能非常的好用,而 SOFA 内部也设计了这个功能,并且内部大量使用了该功能.来看看是如 ...
- SOFA 源码分析 — 自定义线程池原理
前言 在 SOFA-RPC 的官方介绍里,介绍了自定义线程池,可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的.多个服务可以共用一个独立的线程池. API使用方式如 ...
- SOFA 源码分析 — 链路数据透传
前言 SOFA-RPC 支持数据链路透传功能,官方解释: 链路数据透传功能支持应用向调用上下文中存放数据,达到整个链路上的应用都可以操作该数据. 使用方式如下,可分别向链路的 request 和 re ...
随机推荐
- jdbc连接sql数据库
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口 ...
- curl命令备注
curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被广泛应用在Unix.多种Linux发行版中,并且有DOS和Win32.Win64下的移植版本.1.get请求:curl "h ...
- javascript之prototype原型属性
这个地方有点绕,仔细理解代码的意义. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- FFmpeg深入分析(一)
最近在做一个关于监控的项目,要在iphone 客户端实现播放监控的实时视频以及录像视频.使用到了FFmpeg,看到这篇文章,写的非常不错.转自:http://blog.chinaunix.net/ui ...
- jenkin插件整理
分类 plugin名称 wiki地址 源码地址 plugin作用范围 备注 Build Reports构建报告(此类插件用来分析构建结果,比果代码检查,测试CASE分析,并将这些结果以报表,趋势图等形 ...
- OC内存管理-OC笔记
内存管理细节:http://blog.sina.com.cn/s/blog_814ecfa90102vus2.html 学习目标 1.[理解]内存管理 2.[掌握]第一个MRC程序 3.[掌握]内存管 ...
- 《java入门第一季》之Calendar类小案例获取任意二月天数
import java.util.Calendar; import java.util.Scanner; /* * 获取任意一年的二月有多少天 * * 分析: * A:键盘录入任意的年份 * B:设置 ...
- HTML5 移动开发入门知识点
转自:http://www.cnblogs.com/blog-zwei1989/archive/2012/12/12/2815049.html 1.先来看淘宝无线wiki要求在页面中添加的meta标签 ...
- ValueError: setting an array element with a sequence.
http://blog.csdn.net/pipisorry/article/details/48031035 From the code you showed us, the only thing ...
- php 命令空间总结
本文移到:http://www.phpgay.com/Article/detail/classid/2/id/53.html 1.命名空间的语法: <?php namespace 名称; ?&g ...