请选择 进入手机版 | 继续访问电脑版

Dubbo实现不同分支不同测试环境

[复制链接]
小小海 发表于 2021-1-2 18:59:48 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
在对于dubbo的路由机制和注册机制有所相识之后,我们来分析一下如何实现dubbo服务的差异情况隔离。
这一用法的大抵思路为:
正常的测试情况中存在着api-consumer调用user-provider的这么一个调用关系,这里我们暂时称之为default版本。

假设某一天,业务方突然有一个a需求需要开辟改动这个两个模块,此时就应该有这么一个关系链路出现,这里我们暂且称之为 version-a 版本。

但是由于version-a版本照旧待完善阶段,大概尚有一些影响主流程的bug存在,直接发布到测试情况替代掉default版本,大概会影响其他正在测试情况正常运作服务对于default版本的调用情况,因此version-a版本的影响需要被单独限制起来。
抱负的情况下应该是这种情景:

那么如何实现这种单独的隔离方案呢?
现在自己所处的企业主要是接纳dubbo作为微服务架构的根本,所以在举行差异服务情况的隔离时候需要对provider和consumer举行拆分设计。现在在dubbo这块的思路是基于对url设置总线的改造实现,包管差异版本的provider在写入url的时候,会团结需求分支注入一个git.branch的参数:
比方非稳定版本的测试情况中的provider 对应的设置总线中,可以在url的末了中注入一个git.branch参数:
  1. dubbo://192.168.43.227:9096/com.qiyu.dubbo.common.DubboService?anyhost=true&application=order-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&git.branch=master&interface=com.qiyu.dubbo.common.DubboService&methods=doTest&pid=63261&register=true&release=2.7.3&side=provider&threadpool=fixed&threads=200&timestamp=1609484179452
复制代码
然后在举行路由选择的时候,凡是非稳定版本的调用方只要在启动参数中携带有对应的git.branch参数方可实现对该provider的调用,否则都会调用到默认的稳定版本测试情况中。
对应的实现代码模块:
重写对应的zk注册工厂
  1. package com.qiyu.dubbo.router.starter.zone.zk;import org.apache.dubbo.common.URL;import org.apache.dubbo.common.extension.SPI;import org.apache.dubbo.registry.Registry;import org.apache.dubbo.registry.support.AbstractRegistryFactory;import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;/** * @Author idea * @Date created in 3:20 下午 2020/11/26 */public class ZoneAwareZookeeperRegisterFactory extends AbstractRegistryFactory {    private ZookeeperTransporter zookeeperTransporter;    /**     *  dubbo的spi自动具有依赖注入的功能     *     * @param zookeeperTransporter     */    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {        this.zookeeperTransporter = zookeeperTransporter;    }    @Override    public Registry createRegistry(URL url) {        return new ZoneAwareZookeeperRegister(url,zookeeperTransporter);    }}
复制代码
共同对dubbo.properties的改造实现相关模块的注入:
  1. dubbo.registry.protocol=zoneAwareZookeeperRegisterFactory
复制代码
ps:注意,如果希望可以或许匹配到自界说的protocol,而且让dubbo服务在启动的时候注入到ZoneAwareZookeeperRegisterFactory的话,需要在设置注册所在的时候,将协议名称置空,比方这么写:
  1. dubbo.registry.address=127.0.0.1:2181
复制代码
而不是:
  1. dubbo.registry.address=zookeeper://127.0.0.1:2181
复制代码
这一部门可以在源代码的这里查询得到:
  1. org.apache.dubbo.registry.RegistryService#register
复制代码
自界说注册服务的计谋:
  1. package com.qiyu.dubbo.router.starter.zone.zk;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.common.URL;import org.apache.dubbo.registry.zookeeper.ZookeeperRegistry;import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;/** * @Author idea * @Date created in 3:18 下午 2020/11/26 */@Slf4jpublic class ZoneAwareZookeeperRegister extends ZookeeperRegistry {    public ZoneAwareZookeeperRegister(URL url, ZookeeperTransporter zookeeperTransporter) {        super(url, zookeeperTransporter);    }    @Override    public void doRegister(URL url) {        String zone = System.getProperty("git.branch");        url = url.addParameter("git.branch", zone);        log.info("当前注册的url为:{}" , url);        super.doRegister(url);    }}
复制代码
现在可以或许实现差异的provider在注册中心中设置总线url的差异,这样就能在路由router模块起到筛选的效果了。
主要思路:
自界说的一个cluster组件,该cluster组件到场一个叫做ZoneVersionSelectRouter的路由器。
  1. package com.qiyu.dubbo.router.starter.zone.router;import org.apache.dubbo.rpc.Invoker;import org.apache.dubbo.rpc.RpcException;import org.apache.dubbo.rpc.cluster.Cluster;import org.apache.dubbo.rpc.cluster.Directory;import org.apache.dubbo.rpc.cluster.Router;import org.apache.dubbo.rpc.cluster.RouterChain;import org.apache.dubbo.rpc.cluster.directory.AbstractDirectory;import org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker;import java.lang.reflect.Field;import java.util.List;/** * dubbo调用接口之前需要先通过cluster这个组件,在这里做重载,给他注入相关的router设置 * * @author idea * @date created in 10:22 下午 2020/11/21 */public class ZoneAwareCluster implements Cluster {    @Override    public  Invoker join(Directory directory) throws RpcException {        AbstractDirectory ad = (AbstractDirectory) directory;        RouterChain routerChain = ad.getRouterChain();        try {            Field routerField = routerChain.getClass().getDeclaredField("routers");            routerField.setAccessible(true);            List routers = (List) routerField.get(routerChain);            routers.add(new ZoneVersionSelectRouter());            return new FailoverClusterInvoker(directory);        } catch (Exception e) {            e.printStackTrace();        }        return null;    }}
复制代码
该路由组件可以根据consumer端的分支参数,选择性地调用差异的provider。
  1. package com.qiyu.dubbo.router.starter.zone.router;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.common.URL;import org.apache.dubbo.rpc.Invocation;import org.apache.dubbo.rpc.Invoker;import org.apache.dubbo.rpc.RpcException;import org.apache.dubbo.rpc.cluster.Router;import org.springframework.util.StringUtils;import java.util.Arrays;import java.util.List;/** * 自界说的一个router组件: 基于zone参数举行差异版本选择的一个router组件 * * @author idea * @date created in 5:11 下午 2020/11/21 */@Slf4jpublic class ZoneVersionSelectRouter implements Router {    @Override    public URL getUrl() {        return null;    }    @Override    public  List route(List invokers, URL url, Invocation invocation) throws RpcException {        //每次请求都会被切入到这个route模块        String consumerBranch = System.getProperty("git.branch");        log.info(this.getRouterName() + " consumerBranch is {} ", consumerBranch);        Invoker providerInvoker = null;        for (Invoker invoker : invokers) {            String providerBranch = invoker.getUrl().getParameter("git.branch");            if (StringUtils.isEmpty(providerBranch)) {                providerInvoker = invoker;            } else if (providerBranch.equals(consumerBranch)) {                log.info(this.getRouterName() + " providerVersion matched was {} ", providerBranch);                return invokers;            }        }        log.info(this.getRouterName() + " providerVersion matched  default version ");        return Arrays.asList(providerInvoker);    }    @Override    public boolean isRuntime() {        return false;    }    @Override    public boolean isForce() {        return false;    }    @Override    public int getPriority() {        return -100;    }    private String getRouterName() {        return " ====== ZoneVersionSelectRouter ====== ";    }}
复制代码
记得要设置dubbo.properties文件:
  1. dubbo.consumer.cluster=zoneAware
复制代码
最后便是spi设置文件的设置了:

RegisterFactory的spi拓展设置
  1. zoneAwareZookeeperRegisterFactory=com.qiyu.dubbo.router.starter.zone.zk.ZoneAwareZookeeperRegisterFactory
复制代码
Cluster的spi拓展设置
  1. zoneAware=com.qiyu.dubbo.router.starter.zone.router.ZoneAwareCluster
复制代码
启动的时候,到场-Dgit.branch参数,实现差异分支的流量隔离:

一个根本的dubbo服务隔离就根本完成了。
那么我们来举行一下总结,这一方案主要团结了哪些技能?
服务袒露过程中,设置总线的重写规则制定。
服务调用过程中,对于路由层的改造。
dubbo的spi机制明白与实践。

来源:https://blog.csdn.net/Danny_idea/article/details/112062198
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )