dubbo 泛型调用示例 (dubbo generic call)
1. 背景
泛型调用适用于观察者模式,即有很多广泛的消费者,但生产者又不想依赖消费者的client包,比如常见的API开放平台的回调机制;
2. 泛型调用
要实现泛型调用,几个核心点:
- 泛型入参如何构建
- 泛型服务service 如何构建
- 泛型调用结果如何拿到
2.1 泛型入参
泛型入参须是HashMap, 并且第1个参数的key为class, value为实际RPC方法入参的class name,其余参数则为入参类里的字段。示例如下
private Map<String, Object> buildParams() { Map<String, Object> params = new HashMap<>(); params.put("class", "com.my.dubbo.client.generic.TestParams"); params.put("name", "zhangsan"); params.put("id", 1234556); params.put("phone", "12345"); return params; }
2.2 泛型Service
泛型Service须借助dubbo本身提供的缓存机制org.apache.dubbo.config.utils.SimpleReferenceCache,减少每次重复创建Service的开销。
@Test void testGenericCall() throws Exception { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("generic-demo-consumer"); RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setId("dubbo-registry-id"); registryConfig.setAddress("zookeeper://myzk1:port"); registryConfig.setTimeout(20000); applicationConfig.setRegistry(registryConfig); ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>(); referenceConfig.setApplication(applicationConfig); referenceConfig.setInterface("com.my.dubbo.client.generic.HelloService"); referenceConfig.setGeneric("true"); referenceConfig.setVersion("1.0.0"); referenceConfig.setCheck(true); referenceConfig.setGroup("DEMO-GROUP"); referenceConfig.setAsync(true); referenceConfig.setTimeout(10000); SimpleReferenceCache referenceCache = SimpleReferenceCache.getCache(); GenericService genericService = referenceCache.get(referenceConfig); Map<String, Object> params = buildParams(); String[] paramTypes = new String[] {"com.my.dubbo.client.generic.TestParams"};
Object result = genericService.$invoke("sayHello", paramTypes, new Object[]{params});
CountDownLatch latch = new CountDownLatch(1);
CompletableFuture<Object> future = RpcContext.getContext().getCompletableFuture();
future.whenComplete((value, t) -> {
result = value;
System.out.println("invokeAsyncHello(whenComplete): " + value);
latch.countDown();
});
latch.await(5000, TimeUnit.MILLISECONDS);
}
3. 注意事项
SpringBoot应用,需添加EnableDubbo标签才能调用泛型,否则无法获取到genericSerivce实例。
以上。