一、灰度发布介绍
1.什么是灰度测试?
灰度测试,又名AB测试,就是指在同一环境下,根据某种特殊的规则,来实现不同的用户访问到不同的内容的效果。一般可以用于在正式发布前,进行小范围线上测试,或者用于在测试环境中,根据规则来实现一套环境中,可以跑多个版本,却不互相影响的目的。
2.灰度发布的优势
测试有区别于普通的预演环境测试,预演环境可能具有较大的数据量,较好的服务器,但是,预演服务器的环境终究与线上服务器是不完全相同的,例如,线上可能有千万级别的真实数据,但是预演环境可能只有百万级别的脚本写入的虚拟数据。可能线上的服务器有100台,但是预演环境只有10台。而使用灰度发布则是使用线上的服务器进行处理,进行数据库操作时,使用的也是线上数据库,因此可以进行最明确的了解新版本在线上的情况。
除此以外,灰度发布,还可以让正式上线的流程做到完全无感知,平时在服务进行发布时,会因为注册中心的缓存,导致无法及时下线服务,因此还会有请求访问已经停止的服务中,而灰度发布,则可以避免这种情况,可以先将要停止的服务的访问屏蔽,然后再进行服务停止。
二、灰度流程详解
在进行灰度服务选择时,灰度的服务基本规则逻辑是在每个调用方进行处理的,但是具体选择服务所需要的规则的配置数据,则是由前端、配置文件、灰度服务器所连接的数据库,三个地方获取到的。在获取到这些灰度服务的配置,再根据内置的服务规则逻辑来对获取到的注册中心中的服务进行筛选,这样就可以做到灰度测试的效果。
下方的图即为我之前工作的公司中,在前端进行灰度配置的页面:
在这个页面中,可以通过开发1,开发2,client等,来配置不同的请求头信息,通过不同的请求头,就可以在一套服务中,同时对多个版本进行部署测试。当然,这个只是前端配置请求头的效果,在实际引用中,甚至还可以通过后端数据库配置特殊用户信息的方式,来实现灰度的目的。
三、使用SpringCloud进行灰度发布代码开发
1. 服务选择的基本接入
SpringCloud在进行服务选择时,都是通过IRule接口中的choose方法进行服务选择的,在SpringCloud的选择时,默认使用的是RoundRobinRule。如果配置了自己的IRule接口的实现类,就可以用自定义的方法来进行服务选择。下方代码是ABRibbonRule的简单实现。
package com.zhou.ab;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;
import java.util.List;
public class ABRibbonRule extends AbstractLoadBalancerRule{
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
System.out.println("执行了初始化的方法:initWithNiwsConfig");
}
@Override
public Server choose(Object key) {
List<Server> serverList = this.getLoadBalancer().getAllServers();
for (Server server : serverList){
System.out.println("服务列表:"+ server.getHost()+server.getHostPort());
}
int index = (int)(Math.random() * 2);
System.out.println("选择服务:"+ index);
return serverList.get(0);
}
}
2. 前端传递参数进行服务选择
如果希望通过前端传递参数进行选择,就需要在进行Feign的请求时,将客户端发送过来的灰度相关的所有信息进行逐层传递。例如:前端调用A,A调用B,A就需要将前端传递过来的请求中的灰度相关信息传递给服务B。一般我们可以将这个信息保存在请求头中,但是直接这样做存在一些问题的,例如,在某个请求中,创建了新的线程进行处理,那么就无法在新的线程中直接获取到请求头中的信息。需要考虑将请求头信息,保存在线程对象中,在创建新的线程对象时,也要将这些信息进行传递。
3. 使用配置文件进行服务选择配置
如果使用配置文件进行服务选择配置,是最为简单的一种配置方式,但是这种方式进行配置的服务,每一次变更灰度信息,都需要进行重新读取配置文件,甚至重新启动服务来进行,因此这种方式仅在开发环境测试时比较好用,而在线上环境时,是没有任何意义的。
4. 使用数据库进行服务选择配置
使用数据库进行服务选择配置,一般建议另起一个服务,专门用于提供服务的选择,这个服务不会调用任何服务,只会连接自身的ABTest库,提供服务选择配置服务。如果不新起服务,则可能会导致后期的数据库拆分不顺利。同时,如果我们在IRule中进行选择服务时,需要注意不能直接使用FeignClient接口进行选择。因为如果我们使用了FeignClient选择,就会进入一个死循环,如下图所示: