今晚心情无比激动,多云转晴!原因在于弄懂些 Generic Service 实现原理,很有成就感。
各位看官莫笑,今晚,小小的收获,也是非常满足的。下面进入正题!
一、前言
普遍RPC在客户端需要提供接口,如果不提供则无法进行调用。同时,因为客户端也依赖提供的接口,服务端的升级、优化所带来的更新,客户端也要及时的更新API,否则会带来影响。这样,就带来了依赖接口,常常更新API(接口)的麻烦。为了解决这个问题,需要进行泛化调用。
二、使用
在网上一搜,都是Dubbo的泛化调用的例子,可以很少有讲解它的原理的。也不能为了用个泛化调用,就一定要使用Dubbo吧(个人观点:淘宝内部放弃Dubbo,此外配置繁琐,没有人维护,所以不建议使用)。适合的才是最好的,不能生搬硬套。
我google一下,后来发现sofa-rpc框架,里面有泛化调用(在此推荐大家使用sofa-rpc,具体介绍,自己google),下载源码,debug跟着走几遍,Generic Service 实现原理弄懂了。
demo片段如下(下载sofa-rpc的源码,里面有demo):
1 ConsumerConfigconsumerConfig = new ConsumerConfig () 2 .setApplication(applicationConfig) 3 .setInterfaceId(TestGenericService.class.getName()) 4 .setGeneric(true) 5 .setTimeout(50000) 6 .setDirectUrl("bolt://127.0.0.1:22222?appName=generic-server"); 7 GenericService testService = consumerConfig.refer();
// 上面这行中,生成GenericService的动态代理类 8 9 LOGGER.warn("started at pid {}", RpcRuntimeContext.PID); 10 11 while (true) { 12 try { 13 String s1 = (String) testService.$invoke("echoStr", new String[] { "java.lang.String" }, 14 new Object[] { "1111" });
(本文只分析泛化调用的部分,其余部分略过)
三、原理
它的原理无非就是将泛化调用转化为普通调用,关键在于对象的表示和序列化。
看一下流程图:
首先,Client会通过动态代理创建GenericService的代理类;
然后,会经过一系列过滤链(优先级排序,默认不需要,大的优先级高)
ConsumerExceptionFilter order = -20000
RpcReferenceContextFilter order = -19500
ConsumerGenericFilter order = -18000
ConsumerTracerFilter order = -10000
ConsumerInvoker 这里会进行真正的业务的调用
在泛化调用过滤器(ConsumerGenericFilter)中,会进行下列操作:
★设置序列化工厂类型为普通序列化(序列化反序列化均使用SofaSerializerFactory,值为0),并设置到Request参数中。
★进行调用参数($invoke参数)的修正,变成普通的调用参数(调用方法,调用参数类型,调用参数值)
★设置调用类型
最后,使用SOFABolt协议进行进行网络调用。
-----------------------------------------------------------------------------------