ribbon+apollo实现灰度发布

ribbon+apollo实现灰度发布_第1张图片

一、前言

在一般情况下,升级服务器端应用,需要将应用源码或程序包上传到服务器,然后停止掉老版本服务,再启动新版本。但是这种简单的发布方式存在两个问题,一方面,在新版本升级过程中,服务是暂时中断的,另一方面,如果新版本有BUG,升级失败,回滚起来也非常麻烦,容易造成更长时间的服务不可用。

二、Apollo简介

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

三、场景介绍

大致的场景如下,消费端通过gateway访问提供端,提供端为集群部署(A1、A2),我们部署新应用时让所有流量都切换到A1,我们部署A2。当A2部署完成后我们切换部分流量到A2无异常后我们再切换部署A1,这样我们就能实现不停机发布。
ribbon+apollo实现灰度发布_第2张图片

四、实现过程

1.配置提供端eureka元数据:

需要实现灰度发布我们需要用到Eureka注册中心的特性,Eureka的元数据有两种:标准元数据和自定义元数据,这里我们用到了自定义元数据,自定义元数据可以使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,但一般不会改变客户端的行为,除非客户端知道该元数据的含义,例如将提供端集群(A1、A2)分别添加如下配置:
A1:

eureka.instance.metadata-map.group-name=server01

A2:

eureka.instance.metadata-map.group-name=server02

2.Apollo配置中心新增灰度配置:

apollo如何搭建及配置灰度这里就不做介绍官网有详细的文档说明,配置完成后如下图:
ribbon+apollo实现灰度发布_第3张图片
将灰度配置和主配置分别指定集群的不同主机,这样我们的eureka自定义元数据就推送到了相应的服务端。
3.自定义Ribbon规则
在spring cloud Gateway网关中我们自定义Ribbon负载均衡的规则,利用eureka自定义元数据的特性,我们可以在ribbon中获取远程服务的元数据配置,在网关gateway中我们增加如下两项配置:

#指定当前流量引流的集群名称
eureka.instance.metadata-map.group-name=server01
#将规则应用到哪些服务
eureka.instance.metadata-map.gray-server-name=wxt-k3-provider、wxt-act-provider

通过在apollo上我们可以实现动态的切换,将请求流量转发到group-name指定的集群。

Ribbon自定义配置相关代码如下,主要实现了如下两点:

1.获取远程服务的自定义元数据配置。

2.获取网关自定义灰度规则。

2.远端服务配置与gateway配置比较如果一致将流量发送到对应服务。

public class RibbonFilter extends AbstractLoadBalancerRule {

	/**服务分组[all,server01,server02]*/
	@Value("${eureka.instance.metadata-map.group-name}")
	private String appGroupName;
	/**灰度服务[all:所有服务,none:不进行灰度,wxt-xxx-provider,wxt-xxx-provider:指定服务]*/
	@Value("${eureka.instance.metadata-map.gray-server-name}")
	private String grayServerName;

	/**初始随机规则*/
	Random rand = new Random();

	@Override
	public void initWithNiwsConfig(IClientConfig iClientConfig) {

	}

	@Override
	public Server choose(Object o) {
		/**可用服务*/
		List<Server> upList = getLoadBalancer().getReachableServers();
		/**所有服务*/
		List<Server> allList = getLoadBalancer().getAllServers();
		/**服务数*/
		int serverCount = allList.size();
		if (serverCount == 0) {
			return null;
		}
		/**服务名称*/
		String serverName = ((DiscoveryEnabledServer) upList.get(0)).getInstanceInfo().getAppName();
		/**判定是否进入灰度流程*/
		if ("all".equalsIgnoreCase(grayServerName) && !appGroupName.equalsIgnoreCase("all")) {
			return grayStrategy(upList);
		} else if (grayServerName.toUpperCase().contains(serverName) && !appGroupName.equalsIgnoreCase("all")) {
			return grayStrategy(upList);
		} else {
			int index = this.rand.nextInt(serverCount);
			return upList.get(index);
		}
	}

	/** 灰度调用规则*/
	public Server grayStrategy(List<Server> upList) {
		for (Server server : upList) {
			/**服务分组*/
			String upAppGroupName = ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata().get("group-name");
			if (appGroupName.equals(upAppGroupName)) {
				MySlf4j.textInfo("进入灰度规则,服务地址:{0},集群组:{1}", server.getHost(), upAppGroupName);
				return server;
			}
		}
		return null;
	}

}

自此我们完成了灰度部署相关的配置,通过分布式配置中心apollo,我们可以实现不停机维护。

你可能感兴趣的:(Spring,Cloud)