今晚心情無比激動,多雲轉晴!原因在於弄懂些 Generic Service 實現原理,很有成就感。
各位看官莫笑,今晚,小小的收獲,也是非常滿足的。下面進入正題!
一、前言
普遍RPC在客戶端需要提供接口,如果不提供則無法進行調用。同時,因為客戶端也依賴提供的接口,服務端的升級、優化所帶來的更新,客戶端也要及時的更新API,否則會帶來影響。這樣,就帶來了依賴接口,常常更新API(接口)的麻煩。為了解決這個問題,需要進行泛化調用。
二、使用
在網上一搜,都是Dubbo的泛化調用的例子,可以很少有講解它的原理的。也不能為了用個泛化調用,就一定要使用Dubbo吧(個人觀點:淘寶內部放棄Dubbo,此外配置繁瑣,沒有人維護,所以不建議使用)。適合的才是最好的,不能生搬硬套。
我google一下,后來發現sofa-rpc框架,里面有泛化調用(在此推薦大家使用sofa-rpc,具體介紹,自己google),下載源碼,debug跟着走幾遍,Generic Service 實現原理弄懂了。
demo片段如下(下載sofa-rpc的源碼,里面有demo):
1 ConsumerConfig<GenericService> consumerConfig = new ConsumerConfig<GenericService>() 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協議進行進行網絡調用。
-----------------------------------------------------------------------------------
