基于springcloud的灰度实现方案(一)-方案设计

2021/05/18 979点热度 0人点赞 0条评论

5ycode
5ycode

被管理耽误的架构师。工作、学习过程中的知识总结与分享,jvm,多线程,架构设计,经验分享等。
28篇原创内容

公众号

前言

目前所有的服务都是基于springboot/springcloud体系,注册中心使用eureka。

背景:

  • 新的功能上线后,特别是大版本上线,不能完全保证新功能的质量,特别是对历史用户,数据差异性比较大,又无法复现;

  • 为了测试哪套流程的转化率比较高;

想要的效果

图片

这里就会有以下几个问题:

  1. 如果识别是灰度用户? 

  2. 如何识别是灰度服务?

  3. 如何让灰度用户走灰度服务?

  4. 如何让灰度标签传递下去?

系统访问如下:

图片

  1. 用户可以通过网关打上灰度标签;

  2. 用户可以根据网关路由是走api还是走service;

  3. 用户可以根据自定义路由走灰度还是走普通服务;

如何识别灰度用户?

用户在网关里鉴权完成后,根据用户的属性来动态判断;

目前项目里写死了三个用户信息,token分别是:abc,bcd,其他;

其中:

abc: userId = 1  name = 'yxkong'  mobile = '15600000269'

bcd: userId = 901 name = '鱼翔空' mobile = '15600000279'

其他:userId = 901   name = '火星' mobile = '15600000270'

    private String getUserInfo(String token){        if("abc".equals(token)){            return "{\"userId\":\"1\",\"name\":\"yxkong\",\"mobile\":\"15600000269\"}";        }else if("bcd".equals(token)){            return "{\"userId\":\"901\",\"name\":\"鱼翔空\",\"mobile\":\"15600000279\"}";        }else {            return "{\"userId\":\"901\",\"name\":\"火星\",\"mobile\":\"15600000270\"}";        }    }

灰度拦截策略是:

mobile 取模是6 或9

userId 大于等于900 

 rules.add(new LoadBalancerRule("mobile","mod10","6,9","and")); rules.add(new LoadBalancerRule("userId","gte","900","and"));    

如何识别灰度服务?

利用eureka的metadata-map自定义元数据

eureka:  instance:    metadata-map:      version: 2.0      label: gray
# 访问地址(注意,postman访问最好,或者curl,直接chrome访问把xml都过滤l )http://127.0.0.1:8765/eureka/apps/

图片

可以参考下 EurekaInstanceConfigBean,在 instance配置中有个metadataMap 这里可以放置自定义的元数据

package org.springframework.cloud.netflix.eureka;@ConfigurationProperties("eureka.instance")public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware {    private int leaseRenewalIntervalInSeconds = 30;    private int leaseExpirationDurationInSeconds = 90;    private String virtualHostName = "unknown";    private String instanceId;    private String secureVirtualHostName = "unknown";    private String aSGName;    private Map<String, String> metadataMap = new HashMap();}    

如何让灰度用户走灰度服务?

重写ribbon的RoundRobinRule负载均衡策略,在负载均衡的时候,走到对应的服务上。

1,判断是否是灰度用户;2,拿到灰度服务进行路由;

如何让灰度标签传递下去?

通过spring的Interceptor在进入spring的接口请求时,将灰度标签从header中获取并初始化到HystrixRequestContext,本质上是保存在ThreadLocal中

@Configuration@ConditionalOnClass(Servlet.class)public class ServletAutoConfiguration {    @Bean    @ConditionalOnClass(WebHandler.class)    public WebMvcConfigurer configurer() {        return new WebConfig();    }
class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor()).addPathPatterns("/**"); }
private HandlerInterceptor interceptor() { return new HandlerInterceptor() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { GrayHolder.initHystrixRequestContext(request.getHeader(GrayHolder.LABEL_KEY),request.getHeader(GrayHolder.VERSION_KEY)); return true; }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { GrayHolder.shutdownHystrixRequestContext(); } }; } }}

图片
图片

扫码关注

惊喜多多

yxkong

这个人很懒,什么都没留下

文章评论