概述
dubbo的泛化调用, 主要用于客户端没有API接口的情况.参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成.
泛化调用的优缺点
优点: 降低了consumer与provider之间的耦合, consumer只需要知道关注调用的方法, 入参及出参即可
缺点: 参数传递复杂,不方便使用
原理
dubbo的泛化调用主要是通过GenericService接口来处理所有服务请求.
实际上, 泛化调用的实现主要是通过filter来实现的,大致流程如下:
调用 <-> GenericImplFilter <->网络<->GenericFilter <-> 服务实现
而GenericImplFilter和GenericFilter的作用是: 分别在消费者端和提供者端进行序列化的检查和处理。
下面来看GenericImplFilter针对泛化调用的处理源码:
服务端非泛化暴露, 客户端泛化调用
image
服务端泛化暴露, 客户端非泛化调用
image
GenericFilter针对泛化调用的处理源码
image
使用案例(API方式)
ReferenceConfig<GenericService> rc=new ReferenceConfig<>();
GenericService t;
//设置注册信息
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);
//获取真实服务前, 先查询缓存中是否含有该服务
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
t = cache.get(rc);
if (t == null) {
t = rc.get();
cache.destroy(rc);
logger.error("服务不可用");
}
//调用服务
Object invoke = service.$invoke(methodName, "入参类型(数组)", "入参(数组)");
特别注意:
ReferenceConfig是一个特别重的实例,它里面封装了所有与注册中心及服务提供方连接,所以在使用的时候要注意缓存.
如果直接使用reference.get()方法而不是从ReferenceConfigCache.getCache()获取,那么在dubbo管控台会看到每一次调用都会生成一个服务消费者实例,
而堆内存也随着请求的不断增加而变大.