灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行 A/B testing,即让一部分用户继续用产品特性 A,一部分用户开始用产品特性 B,如果用户对 B 没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到 B 上面来。
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
原理讲解
灰度发布的原理其实就是对请求进行分流,可以让指定的用户访问指定的具有新功能的服务,其他的用户还是使用老的服务。既然是对请求进行分流,那么这个还是可以在 API 网关中统一处理,网关是对外的入口,当用户的请求过来时,我们可以将特定的用户请求转发到我们刚刚发布好的具有新功能的服务上去。
核心点还是在转发上做文章,那么就必须要对 Ribbon 进行改造了,因为 Zuul 中使用 Ribbon 来发现需要转发的实例,要想实现请求的分流来做灰度发布,就必须改造 Ribbon,不是改造源码,开源的框架扩展性都非常好,Ribbon 已经为我们提供了一个非常方便的扩展,就是自定义负载均衡策略,通过自定义负载均衡策略我们就可以在里面加上灰度发布的逻辑。
灰度发布只是在系统需要发布新功能时才会用到,并且需要轮流切换,首先将 A 机器上的服务变成灰度发布的状态,隔离所有请求,然后重新发布,验证好了之后重新发布另外机器上的服务。需要用到我们的 Apollo 配置中心来管理需要进行灰度发布的服务信息以及用户信息,这样才可以做到轮流切换。
总结下来我们只需要实现两点就可以达到灰度发布的效果,分别是:
1)将灰度的服务从正常的服务中移除,这样 Ribbon 在进行 Server 选择的时候就不会选择到已经被设置成灰度发布的 Server。
2)获取当前请求的用户 ID,如果这个用户是我们已经配置成灰度发布用户中的一员,那就从所有可用的服务中去对比灰度发布的服务,能找到那就直接返回,这样就能针对指定的用户使用我们配置的灰度服务了。
根据用户做灰度发布
首先创建一个 Apollo 配置文件,用来存储需要进行灰度发布的服务信息以及用户信息,也就是说这个配置中的灰度发布服务只能由配置中的用户访问,别的用户是不能访问的,以此来达到分流的目的,见如下代码。
@Data
@Configuration
public class BasicConf {
@Value("${grayPushServers:default}")
private String grayPushServers;
@Value("${grayPushUsers:default}")
private String grayPushUsers;
}
创建灰度发布的过滤器,用于将配置信息传递到自定义的负载均衡类中去,见如下代码。
public class GrayPushFilter extends ZuulFilter {
@Autowired
private BasicConf basicConf;
public GrayPushFilter() {
super();
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
Object success = ctx.get("isSuccess");
return success == null ? true : Boolean.parseBoolean(success.toString());
}
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
retu