原理:通過請求頭埋入指定服務的metadata標識,擴展ribbon的choose策略。
- 下載源碼編譯
應用集成
maven依賴
<dependency>
<groupId>io.jmnarloch</groupId>
<artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>
<version>2.1.0</version>
</dependency>
- 應用配置
#AB測試用,網關會根據該參數路由
spring.cloud.nacos.discovery.metadata.launcher=A
- 攔截器
public class AbTestingFilter extends OncePerRequestFilter {
private final static String SWITCH_KEY = "launcher",
SWITCH_HEAD_KEY = "switchTag",
DEFAULT_ENV = "B";//默認B爲線上測試環境
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String switchTag = httpServletRequest.getHeader(SWITCH_HEAD_KEY);
log.info("head switch tag = {}", switchTag);
try {
if (DEFAULT_ENV.equals(switchTag)) {
// 開啓ribbon的灰度開關(線程級別)
RibbonFilterContextHolder.getCurrentContext().add(SWITCH_KEY, DEFAULT_ENV);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
} finally {
if (DEFAULT_ENV.equals(switchTag))
RibbonFilterContextHolder.getCurrentContext().remove(SWITCH_KEY);
}
}
}
- feign conf
增加請求頭,自定義全局的feign interceptor
@Bean
public RequestInterceptor newRequestInterceptor(@Value("${spring.cloud.nacos.discovery.metadata.launcher:A}") String tag) {
return requestTemplate -> requestTemplate.header("switchTag", tag);
}
zuul網關集成
則參考如下代碼
maven依賴同上
攔截器
public class TestingAbFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return -1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//是否需要做AB切換
if (request.getParameter("foo") != null) {
//重寫請求頭新增AB開關透傳到下游服務
ctx.addZuulRequestHeader("switchTag", "A");
RibbonFilterContextHolder.getCurrentContext().add("launcher", "A");
} else {
RibbonFilterContextHolder.getCurrentContext().add("launcher", "B");
}
return null;
}
}