dubbo实战之“动态调用服务”(实为“泛化调用”)探索
作者:互联网
一、简介
需求:Dubbo的调用方,在不引入服务接口类的情况下,远程调用其他Dubbo服务。
二、项目依赖
SpringBoot整合Dubbo3.x关于curator和zookeeper版本选型的思考
经尝试,使用高版本组合(Curator 5.2.0 + ZooKeeper 3.6.3)
三、核心代码
如果引用的是 Dubbo 3.0.5
import cn.hutool.core.util.StrUtil;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.utils.SimpleReferenceCache;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.lang.Nullable;
/**
* 功能描述: 基于 Dubbo 泛化调用特性的远程调用
*
* @author geekziyu
* @version 1.0.0
*/
class DubboRpc {
private RegistryConfig registry;
DubboRpc(ApplicationConfig application, RegistryConfig registry) {
this.registry = registry;
ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(application);
}
Object genericInvoke(String interfaceClass, String methodName, String[] parameterTypes, Object[] args) {
return genericInvoke(interfaceClass, methodName, parameterTypes, args, null, null);
}
Object genericInvoke(String interfaceClass, String methodName, String[] parameterTypes, Object[] args, @Nullable String group, @Nullable String version) {
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setRegistry(registry);
reference.setInterface(interfaceClass); // 接口名
reference.setGeneric("true"); // 声明为泛化接口
if (StrUtil.isNotBlank(group)) { // NOSONAR
reference.setGroup(group);
}
if (StrUtil.isNotBlank(version)) {// NOSONAR
reference.setVersion(version);
}
// ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,
// 需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
// API方式编程时,容易忽略此问题。
// 这里使用dubbo内置的简单缓存工具类进行缓存
SimpleReferenceCache cache = SimpleReferenceCache.getCache();
GenericService genericService = cache.get(reference);
// 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
return genericService.$invoke(methodName, parameterTypes, args);
}
}
如果引用的是 Dubbo 3.0.1
import cn.hutool.core.util.StrUtil;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericService;
import javax.annotation.Nullable;
/**
* 功能描述: 基于 Dubbo 泛化调用特性的远程调用
*
* @author 20024968@cnsuning.com
* @version 1.0.0
*/
class DubboRpc {
private RegistryConfig registry;
DubboRpc(ApplicationConfig application, RegistryConfig registry) {
this.registry = registry;
ApplicationModel.getConfigManager().setApplication(application);
}
Object genericInvoke(String interfaceClass, String methodName, String[] parameterTypes, Object[] args) {
return genericInvoke(interfaceClass, methodName, parameterTypes, args, null, null);
}
Object genericInvoke(String interfaceClass, String methodName, String[] parameterTypes, Object[] args, @Nullable String group, @Nullable String version) {
referenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setRegistry(registry);
reference.setInterface(interfaceClass); // 接口名
reference.setGeneric("true"); // 声明为泛化接口
if (StrUtil.isNotBlank(group)) { // NOSONAR
reference.setGroup(group);
}
if (StrUtil.isNotBlank(version)) {// NOSONAR
reference.setVersion(version);
}
// ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,
// 需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
// API方式编程时,容易忽略此问题。
// 这里使用dubbo内置的简单缓存工具类进行缓存
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);
// 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
return genericService.$invoke(methodName, parameterTypes, args);
}
}
至于这个 RegistryConfig 可以这样:
@Service
public class RpcInvokerService implements InitializingBean {
@Value("${dubbo.application.name}")
private String applicationName;
@Value("${dubbo.registry.protocol}")
private String protocol;
@Value("${dubbo.registry.address}")
private String address;
private DubboRpc rpc;
@Override
public void afterPropertiesSet() {
ApplicationConfig application = new ApplicationConfig(applicationName);
RegistryConfig registry = new RegistryConfig();
registry.setProtocol(protocol);
registry.setAddress(address);
rpc = new DubboRpc(application, registry);
}
// ...
}
标签:dubbo,调用,泛化,reference,registry,org,import,String 来源: https://www.cnblogs.com/kendoziyu/p/dubbo-GenericService-invoke.html