概述
dubbo的泛化調(diào)用, 主要用于客戶端沒有API接口的情況.參數(shù)及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成.
泛化調(diào)用的優(yōu)缺點(diǎn)
優(yōu)點(diǎn): 降低了consumer與provider之間的耦合, consumer只需要知道關(guān)注調(diào)用的方法, 入?yún)⒓俺鰠⒓纯?/p>
缺點(diǎn): 參數(shù)傳遞復(fù)雜,不方便使用
原理
dubbo的泛化調(diào)用主要是通過GenericService接口來處理所有服務(wù)請求.
實(shí)際上, 泛化調(diào)用的實(shí)現(xiàn)主要是通過filter來實(shí)現(xiàn)的,大致流程如下:
調(diào)用 <-> GenericImplFilter <->網(wǎng)絡(luò)<->GenericFilter <-> 服務(wù)實(shí)現(xiàn)
而GenericImplFilter和GenericFilter的作用是: 分別在消費(fèi)者端和提供者端進(jìn)行序列化的檢查和處理。
下面來看GenericImplFilter針對泛化調(diào)用的處理源碼:
服務(wù)端非泛化暴露, 客戶端泛化調(diào)用

image
服務(wù)端泛化暴露, 客戶端非泛化調(diào)用

image
GenericFilter針對泛化調(diào)用的處理源碼

image
使用案例(API方式)
ReferenceConfig<GenericService> rc=new ReferenceConfig<>();
GenericService t;
//設(shè)置注冊信息
ApplicationConfig application=new ApplicationConfig();
application.setName(appName);
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(zookeeperUrl);
rc.setRegistry(registryConfig);
rc.setGeneric(true);
rc.setVersion(version);
rc.setGroup(group);
rc.setApplication(application);
rc.setInterface(interfaceName);
rc.setTimeout(5000);
//獲取真實(shí)服務(wù)前, 先查詢緩存中是否含有該服務(wù)
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
t = cache.get(rc);
if (t == null) {
t = rc.get();
cache.destroy(rc);
logger.error("服務(wù)不可用");
}
//調(diào)用服務(wù)
Object invoke = service.$invoke(methodName, "入?yún)㈩愋?數(shù)組)", "入?yún)?數(shù)組)");
特別注意:
ReferenceConfig是一個特別重的實(shí)例,它里面封裝了所有與注冊中心及服務(wù)提供方連接,所以在使用的時候要注意緩存.
如果直接使用reference.get()方法而不是從ReferenceConfigCache.getCache()獲取,那么在dubbo管控臺會看到每一次調(diào)用都會生成一個服務(wù)消費(fèi)者實(shí)例,
而堆內(nèi)存也隨著請求的不斷增加而變大.