文章目录
Spring Cloud使用Zuul和Ribbon做灰度发布
关注可以查看更多粉丝专享blog~
公司产品线采用的是Spring Cloud(Dalston.SR1)、Spring Boot(1.5.x)、Spring MVC、Mybatis、Redis构建的微服务、服务数量60+,之前规定是每周二中午12点-2点发布,由于用户访问量的上升这样用户体验特别差,之前为了解决这个问题做过一次不停机发布方案,采用的是Spring Cloud优雅停机,具体方式如下:
- maven添加actuator依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- application.yml中配置
endpoints.shutdown.enabled: true #启用shutdown端点,以便支持优雅停机
#endpoints.shutdown.sensitive: false #禁用密码验证(可选)
- 在任意一台服务器上利用curl发送shutdown命令
curl -X POST http://ip:端口/shutdown
或者
curl -d "" http://ip:端口/shutdown
回忆过去
在Jenkins脚本中配置打包完毕之后先对要发布的那台服务器发送shutdown命令,会收到{“message”:“Shutting down, bye…”},问题就出在这里,服务器在收到该指令之后会从eureka退出,有时候是从eureka直接注销,但是有时候会出现(down)标识,这个时候服务器还可以接收到请求,但是已经开始发布了,所以用户请求如果负载到该机器就会出现服务器错误,体验很差。难道要告诉用户我们在发布,现在不能用吗?NO!要不凌晨再发布吧?NONONO!!!所以开始了探索之路。
展望未来
网上有很多关于Spring Cloud灰度发布的策略,包括K8S,Apollo、Ribbon等,K8S成本太高了,pass!我们配置中心采用的是Spring Cloud Config所以Apollo pass!最终采用的是zuul和Ribbon来做灰度发布,其实主要方式就是网关拦截请求,通过识别请求头中的特定标识来识别是否灰度用户,从而将用户路由到灰度服务上面。我们没有灰度测试流程所以本次我只做了后半部分,在灰度发布的时候将用户路由到正常服务上面,待发布完成一台之后调用服务的/health接口确定启动成功,则灰度剩下的机器,由刚发布完的机器提供服务以此来避免服务器错误的情况。做到随时发布,其实里面还有一些问题,比如接口涉及到版本问题这么简单粗暴是不可行的,后面的路还很长,本次先记录我的不停机发布之旅。
大致流程分为以下几步
1、定义自定义灰度策略配置文件
GrayRibbonConfig(在GrayRibbonConfig类中指定我们的灰度发布规则类)
import com.*.*.*.ExcludeFromComponetScan;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
/**
* ribbon要排除在ComponentScan之外故新建此包 by david
*/
@Slf4j
@Configuration
@ExcludeFromComponetScan
public class GrayRibbonConfig {
@Bean
public IRule grayRule() {
log.info("---customize gray publish---");
return new GrayRule();
}
}
RibbonClientConfig(使用@RibbonClients(defaultConfiguration = GrayRibbonConfig.class)指定客户端路由配置为GrayRibbonConfig类,该注解为全局配置,如果有服务需要特殊处理则需要使用@RibbonClient(configuration = Xxx.class)自定义配置)
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ConfigurationBasedServerList;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import lombok.extern.slf4j.Slf4j;
/**
* 自定义灰度策略
*/
@Slf4j
@RibbonClients(defaultConfiguration = GrayRibbonConfig.class)
public class RibbonClientConfig {
public static class BazServiceList extends ConfigurationBasedServerList {
public BazServiceList(IClientConfig config) {
super.initWithNiwsConfig(config);
}