Dubbo泛化调用!

一般情况下我们通过RPC调用接口提供方的服务,首先在消费端嵌入提供方的Jar包,从而使用Jar包中的类和方法。

在通用的API网关系统中,考虑到扩展性和维护成本,不会使用服务提供方客户端的JAR包,而是通过泛化调用。

其中的原理跟普通的RPC调用时一致的,网络序列化反射这些底层的技术原理一致。

  • 区别在于参数和返回值都用Map来表示。

任何一个成熟的RPC框架都会支持泛化调用,比如Dubbo提供的泛化。

泛化接口调用方式主要用于客户端没有API接口的情况,参数及返回值中的所有入参出参均用Map表示,通常用于框架集成。

  • 比如:实现一个通用的API网关或者服务测试框架。

可通过 GenericService 调用所有服务实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.apache.dubbo.rpc.service.GenericService; 
...

// 引用远程服务
// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.xxx.XxxService");
reference.setVersion("1.0.0");
// 声明为泛化接口
reference.setGeneric(true);

// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();

// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("sayHello", new String[] {"java.lang.String"}, new Object[] {"world"});

// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map<String, Object> person = new HashMap<String, Object>();
person.put("name", "xxx");
person.put("password", "yyy");
// 如果返回POJO将自动转成Map
Object result = genericService.$invoke("findPerson", new String[]
{"com.xxx.Person"}, new Object[]{person});

...