使用春云体系怎么实现标签路由?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
<强>问题:强>
1,本地连上开发或测试环境的集群连调,正常测试请求可能会请求到本地,被自己的调试阻塞。
2,测试环境维护时,多项目并发提测,维护多个相同的集群进行测试是否必要,是否有更好的方案。
一般,我们在使用春云全家桶的时候,会选择zuul作为网关,丝带作为负载均衡器,假装作为远程服务调用模版。使用过春云的同学对这些组件的作用必然非常熟悉。这里就拿这些组件组合成的微服务集群来实现标签路由的功能。
实现的效果如图所示,在头上带上标签的请求会在经过网关和各个应用时进行标签判断流量应该打到哪一个去,而每一个应用自己本身的标签是通过尤里卡上的matedate实现的。
如下图可以构想动态修改标签控制应用所能承接的请求,这里暂时不描述mq部分的功能:
@Override public AbstractServerPredicate  getPredicate (), { OfflineEnvMetadataAwarePredicate 才能;OfflineEnvMetadataAwarePredicate =, new OfflineEnvMetadataAwarePredicate (); offlineEnvMetadataAwarePredicate.setEnv才能(env); return 才能;offlineEnvMetadataAwarePredicate; }
谓词的实现屏蔽了开发测试环境中非这个环境网段启动的应用,并且比对请求的标签和本地的标签,来控制路由给哪一个服务器。
@Override public AbstractServerPredicate  getPredicate (), { OfflineEnvMetadataAwarePredicate 才能;OfflineEnvMetadataAwarePredicate =, new OfflineEnvMetadataAwarePredicate (); offlineEnvMetadataAwarePredicate.setEnv才能(env); return 才能;offlineEnvMetadataAwarePredicate; }
那么我们注意到请求头上的标签要在初始时就拿到,所以需要一个ServletRequestListener,将拿到的区域放入RequestZoneLabelContext。我们知道在一个请求中如果是一个io线程执行到底,我们只需要利用threadlocal来存储线程变量,可是如果一个请求中会产生不定的子线程完成,数据在线程间的传递就成为问题,这里使用了InheritableThreadLocal来决解,在RequestZoneLabelContext中可以看到。
public class RequestZoneLabelContextListener implements ServletRequestListener { private 才能static final  String ZONE_LABEL_NAME =,“zone"; @Override才能 public 才能;void  requestDestroyed (ServletRequestEvent 行为),{ ,,,RequestZoneLabelContext.remove (); ,,} @Override才能 public 才能;void  requestInitialized (ServletRequestEvent requestEvent), { ,,,HttpServletRequest request =, (HttpServletRequest) requestEvent.getServletRequest (); ,,,String lbZone =, request.getHeader (ZONE_LABEL_NAME); ,,,如果(StringUtils.isNotBlank (lbZone)) { ,,,,,RequestZoneLabelContext.setZone (lbZone); ,,,} ,,} }
/* * *大敌;从request 标题上传递标签到假装请求 ,*/public class  RequestZoneLabelContext { private 才能static InheritableThreadLocal< String>, zoneLabelThreadLocal =, new InheritableThreadLocal<在(); public 才能static void  setZone (String 区){ ,,,zoneLabelThreadLocal.set(区); ,,} public 才能static String  getRequestZone () { ,,,return zoneLabelThreadLocal.get (); ,,} public 才能;static  void 删除(){ ,,,zoneLabelThreadLocal.remove (); ,,} }
那么在应用之间调用的假装中我们是需要继续把这个带通过头传递下去的,所以又扩展了RequestInterceptor:
public class FeignZoneHeaderInterceptor implements RequestInterceptor { @Override才能 public 才能;void 应用(RequestTemplate 模板),{ ,,,String requestZone =, RequestZoneLabelContext.getRequestZone (); ,,,如果(StringUtils.isNotBlank (requestZone)) { ,,,,,template.header (“zone",, requestZone); ,,,} ,,} }使用春云体系怎么实现标签路由