打标签
写个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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)
![img](https://img-blog.csdnimg.cn/img_convert/39fb404993a8aca991d3e085a8c6f0a5.jpeg)
总结
谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。
为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的
并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)
66个Java面试知识点
架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)
算法刷题(PDF)
《一线大厂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面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!