Dubbo下的多版本并行开发测试解决方案(服务路由)

简单代码


打标签

写个Register的Wrapper类 将标签注册上去 这里我是将标签绑定到了dubbo的属性application; 放在哪里自己决定能读取到就行;

/**

  • @author shirenchuang

  • Registry 的包装类

  • 修改URL 中的Application

  • @date 2019/12/5 8:35 下午

*/

public class DevVersionRegisterWrapper implements Registry {

private static final Logger logger = LoggerFactory.getLogger(“devVersion”);

private Registry registry;

/**

  • 注入Register

  • @param registry

*/

public DevVersionRegisterWrapper(Registry registry) {

this.registry = registry;

}

@Override

public URL getUrl() {

return DevVersionRegisterFactoryWrapper.changeApplication(registry.getUrl());

}

@Override

public boolean isAvailable() {

return registry.isAvailable();

}

@Override

public void destroy() {

registry.destroy();

}

@Override

public void register(URL url) {

registry.register(DevVersionRegisterFactoryWrapper.changeApplication((url)));

}

@Override

public void unregister(URL url) {

registry.register(DevVersionRegisterFactoryWrapper.changeApplication((url)));

}

@Override

public void subscribe(URL url, NotifyListener listener) {

registry.subscribe(DevVersionRegisterFactoryWrapper.changeApplication((url)),listener);

}

@Override

public void unsubscribe(URL url, NotifyListener listener) {

registry.unsubscribe(DevVersionRegisterFactoryWrapper.changeApplication((url)),listener);

}

@Override

public List lookup(URL url) {

return registry.lookup(DevVersionRegisterFactoryWrapper.changeApplication((url)));

}

}

写一个RegistryFactory的包装类

/**

  • @author shirenchuang

  • RegistryFactory 的包装类,在注册的时候 修改一下 Application

  • 如果是 迭代环境则把Appliacation=Application_迭代版本号

  • @date 2019/12/5 8:29 下午

*/

public class DevVersionRegisterFactoryWrapper implements RegistryFactory {

private static final Logger logger = LoggerFactory.getLogger(“devVersion”);

private RegistryFactory registryFactory;

/**

  • 注入RegisterFactory

*/

public DevVersionRegisterFactoryWrapper(RegistryFactory registryFactory) {

this.registryFactory = registryFactory;

}

@Override

public Registry getRegistry(URL url) {

//获取当前环境的迭代版本号

if(!StringUtils.isEmpty(MyThreadLocal.localVersion)){

logger.info(“=启动的服务是迭代版本服务 devVersion:{}=”,MyThreadLocal.localVersion);

System.out.println(“====启动的服务是迭代版本服务 devVersion:”+MyThreadLocal.localVersion);

return new DevVersionRegisterWrapper(registryFactory.getRegistry(changeApplication(url)));

}

logger.info(“=启动的服务是稳定版本”);

System.out.println(“=启动的服务是稳定版本”);

return registryFactory.getRegistry(url);

}

public static URL changeApplication(URL url){

if(!StringUtils.isEmpty(MyThreadLocal.localVersion)){

String applicationKey = url.getParameter(Constants.APPLICATION_KEY)+MyThreadLocal.spiltString+MyThreadLocal.localVersion;

URL url2 = url.addParameter(Constants.APPLICATION_KEY,

applicationKey);

logger.info(“=====迭代版本服务修改 Application key:{} =====”,applicationKey);

return url2;

}

return url;

}

}

服务路由

Invoker 包装类

/**

  • @author shirenchuang

  • 2019/12/10

  • 集群扩展包装器

  • 参照 {@link com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker}

*/

public class DevVersionClusterInvoker implements Invoker {

private static final Logger logger = LoggerFactory.getLogger(“devVersion”);

private final Directory directory;

private final Invoker invoker;

public DevVersionClusterInvoker(Directory directory, Invoker invoker) {

this.directory = directory;

this.invoker = invoker;

}

@Override

public URL getUrl() {

return directory.getUrl();

}

@Override

public boolean isAvailable() {

return directory.isAvailable();

}

@Override

public void destroy() {

this.invoker.destroy();

}

@Override

public Class getInterface() {

return directory.getInterface();

}

@Override

public Result invoke(Invocation invocation) throws RpcException {

// 找到迭代版本号

return doDevVersionInvoke(invocation, null);

}

@SuppressWarnings({“unchecked”, “rawtypes”})

private Result doDevVersionInvoke(Invocation invocation, RpcException e) {

Result result ;

Invoker minvoker;

List<Invoker> devVersionInvokers = selectDevVersionInvoker(invocation);

if (devVersionInvokers==null||devVersionInvokers.size()==0) {

logger.error("没有找到服务啊~~~~ ");

throw new RpcException(“没有找到服务啊~~~~”);

} else {

minvoker = devVersionInvokers.get(0);

}

try {

result = minvoker.invoke(invocation);

} catch (RpcException me) {

if (me.isBiz()) {

result = new RpcResult(me.getCause());

} else {

throw new RpcException(me.getCode(), getDevVersionExceptionMessage(e, me), me.getCause());

}

} catch (Throwable me) {

throw new RpcException(getDevVersionExceptionMessage(e, me), me.getCause());

}

return result;

}

private String getDevVersionExceptionMessage(Throwable t, Throwable mt) {

String msg = "devVersion error : " + mt.getMessage();

if (t != null) {

msg = msg + “, invoke error is :” + StringUtils.toString(t);

}

return msg;

}

/**

  • 获取对应迭代版本服务

  • @param invocation

  • @return

*/

private List<Invoker> selectDevVersionInvoker(Invocation invocation) {

List<Invoker> invokers = null;

if (invocation instanceof RpcInvocation) {

try {

/其实我们也可以给directory生生一个代理类,来做帅选操作/

invokers = directory.list(invocation);

//经过了dubbo的栓选之后,我们来找自己需要的Invokes

String devVersion = MyThreadLocal.getDevVersion();

List<Invoker> newInvokers = new ArrayList<>();

List<Invoker> stableInvokers = new ArrayList<>();

for (Invoker invoker : invokers){

URL providerUrl ;

//获取应用名称

Method getProviderUrl = invoker.getClass().getDeclaredMethod(“getProviderUrl”);

getProviderUrl.setAccessible(true);

providerUrl = (URL)getProviderUrl.invoke(invoker);

String application = providerUrl.getParameter(Constants.APPLICATION_KEY);

if(StringUtils.isEmpty(devVersion)){

if(application.indexOf(MyThreadLocal.spiltString)==-1){

//不是迭代过来或者本身不是迭代的请求 只能访问非迭代版本

newInvokers.add(invoker);

}

}else {

//是迭代的请求 就需要找对应的迭代服务

if(application.indexOf(MyThreadLocal.spiltString)!=-1){

String version = application.substring(application.indexOf(MyThreadLocal.spiltString)+5);

if(version.equals(devVersion)){

newInvokers.add(invoker);

}

}

}

//找到稳定环境

if(application.indexOf(MyThreadLocal.spiltString)==-1){

stableInvokers.add(invoker);

}

}

if(newInvokers==null||newInvokers.size()==0){

String serviceName = directory.getInterface().getName();

if(StringUtils.isEmpty(devVersion)){

String error = “=====当前消费者自身版本和迭代传递版本均为稳定版本~ ,但是没有找到将要消费的服务=>”+serviceName+" 的稳定版本!!";

logger.error(error);

throw new RuntimeException(error);

}else {

// 请求的是迭代服务, 但是迭代服务没有找到,退而求其次调用稳定环境 )

if(stableInvokers!=null&&stableInvokers.size()>0){

StringBuffer sb = new StringBuffer();

sb.append(“=======当前cap请求的版本为:”).append(devVersion)

.append(“;往后传递版本”).append(devVersion).append(“; 将要消费的服务:”).append(serviceName)

.append(“没有找到与之对应的迭代版本;将会调用稳定版本”);

logger.info(sb.toString());

return stableInvokers;

}else {

//可能有其他的迭代服务,但是不调用

logger.error(“当前请求迭代版本:{},但是不存在迭代服务,也没有找到稳定服务;{},{},{}”,devVersion,serviceName);

throw new RuntimeException(“当前请求迭代版本:”+devVersion+“,但是不存在迭代服务,也没有找到稳定服务;”+serviceName);

}

}

}else {

return newInvokers;

}

} catch (RpcException e) {

logger.error(“获取 迭代版本 的服务时 发生错误~~:”+ directory.getUrl().getServiceInterface() + “, method:” + invocation.getMethodName()

, e);

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

}

return invokers;

}

@Override

public String toString() {

return “invoker :” + this.invoker + ",directory: " + this.directory;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

img

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

算法刷题(PDF)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
ttps://img-community.csdnimg.cn/images/e5c14a7895254671a72faed303032d36.jpg" alt=“img” style=“zoom: 33%;” />

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

[外链图片转存中…(img-NZejwODc-1711593673920)]

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

[外链图片转存中…(img-VKsGlWOU-1711593673921)]

算法刷题(PDF)

[外链图片转存中…(img-M1RNxrBU-1711593673921)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值