代码技巧——dubbo编程式调用

日常开发中,使用dubbo的场景为:

(1)A业务依赖B业务的能力,B业务开发好dubbo接口,把接口定义(方法、出入参DTO、enum、constants等)打在二方包,由A应用在pom中引用依赖包;
(2)B应用启动服务,如通过@DubboService注解并指定version、timeout、group等把处理逻辑的service注册为bean,暴露dubbo接口的地址到zk;
(3)A应用启动服务,如通过@DubboReference注解并指定version、timeout、group等把B的接口注册为bean,在代码中调用接口的方法(通过查找zk的服务方地址远程RPC调用);

现在有一种新的场景,A提供接口规范(方法及出入参),由B、C、D等多个业务方来实现这个接口,并将各自的服务以dubbo的形式注册到zk(以group区分);A在业务处理逻辑中,通过业务参数找到对应的group,然后在代码中调用对应group的dubbo接口;

因为业务方的数量是不确定的,也就是说A不知道当前有哪些接入方,因此不能提前在代码中使用@DubboReference注解配置各个provider的bean,仅知道自己定义的接口定义和给各个业务方分配的默认group;这时,就需要A在代码中能「编程式动态」调用dubbo;

下面给出代码实例:

(1)A应用定义的接口规范

/**
 * A应用定义的接口规范
 */
public interface BaseFacade {
    
    /**
     * 查询
     *
     * @param requestDTO
     * @return
     */
    Return<String> query(RequestDTO requestDTO);
}

(2)B、C、D等多个业务方来实现这个接口,配置好group,部署服务注册到zk

/**
 * 实现A应用定义的接口规范
 */
@Slf4j
@DubboService(group = "${baseFacade .group}", version = "1.0.0", timeout = 5000)
public class BaseFacadeImpl implements BaseFacade {

    @Override
    public Return<String> query(RequestDTO requestDTO) {
        // ...
    }

}

(3)A应用编程式调用B、C、D的dubbo接口(理论上ZK的dubbo服务都可以泛化调用)

/**
 * @author Akira
 */
@Slf4j
@Service
public class SimpleDynamicInvoker {

    /**
     * dubbo provider 缓存
     */
    private static final Map<String, BaseFacade> servicesCache = Maps.newConcurrentMap();

    /**
     * A定义的接口名
     */
    private static final String INTERFACE_NAME = BaseFacade.class.getName();

    @Resource
    private DefaultListableBeanFactory beanFactory;

    /**
     * 根据groupId初始化对应的provider
     *
     * @param groupId
     */
    private void initProvider(String groupId) {
        if (servicesCache.containsKey(groupId)) {
            return;
        }
        String beanId = "BaseFacade#" + groupId;
        RootBeanDefinition serviceBeanDefinition = new RootBeanDefinition();
        // class为org.apache.dubbo.config.spring.ReferenceBean
        serviceBeanDefinition.setBeanClass(ReferenceBean.class);
        serviceBeanDefinition.setLazyInit(false);
        serviceBeanDefinition.getPropertyValues().addPropertyValue("version", "1.0.0");
        serviceBeanDefinition.getPropertyValues().addPropertyValue("interface", INTERFACE_NAME);
        serviceBeanDefinition.getPropertyValues().addPropertyValue("group", groupId);
        serviceBeanDefinition.getPropertyValues().addPropertyValue("id", beanId);
        beanFactory.registerBeanDefinition(beanId, serviceBeanDefinition);
        // 注册bean 返回bean实例
        BaseFacade facadeBean = beanFactory.getBean(beanId, BaseFacade.class);
        servicesCache.put(groupId, facadeBean);
        log.info("注册provider成功. [groupId={}]", groupId);
    }

    /**
     * 执行provider调用
     *
     * @param groupId
     * @param param
     * @return
     */
    public Return<String> invokeByGroupId(String groupId, RequestDTO param) {
        if (!servicesCache.containsKey(groupId)) {
            initProvider(groupId);
        }
        final BaseFacade baseFacade = servicesCache.get(groupId);
        return baseFacade.query(param);
    }

}

参考:

dubbo实战之“动态调用服务”(实为“泛化调用”)探索 - 极客子羽 - 博客园

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值