应用程序升级面临最大挑战是新旧业务切换,将软件从测试的最后阶段带到生产环境,同时要保证系统不间断提供服务
长期以来,业务升级渐渐形成了几个发布策略:蓝绿发布、灰度发布和滚动发布,目的是尽可能避免因发布导致的流量丢失或服务不可用问题
指同时运行两个版本的应用,部署的时候,并不停止掉老版本,而是直接部署一套新版本,等新版本运行起来后,再将流量切换到新版本上
发布策略简单
用户无感知,平滑过渡
升级/回滚速度快
如果出问题,影响范围较大
成本较高
每次只升级一个或多个服务,升级完成后加入生产环境,不断执行这个过程,直到集群中的全部旧版本升级新版本
滚动发布能够解决掉蓝绿部署时对硬件要求增倍的问题,也可以使用临时一台或多台服务器进行替换
用户无感知,平滑过渡
如果出问题,影响范围较小
节约资源
部署时间慢,取决于每阶段更新时间
发布策略较复杂
无法确定没问题的环境,不易回滚
只升级部分服务,即让一部分用户继续用老版本,一部分用户开始用新版本,如果用户对新版本没什么意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来
保证整体系统稳定性,在初始灰度的时候就可以发现、调整问题,影响范围可控
新功能逐步评估性能,稳定性和健康状况,如果出问题影响范围很小,相对用户体验也少
用户无感知,平滑过渡
流量配比递增的配置修改,带来额外的操作成本
用户覆盖狭窄,低比例流量未必能发现所有问题
当调用请求从网关或者服务发起的时候,通过 Header、Parameter、Cookie 一种或者几种参数进行驱动,在路由过滤中,根据这些参数实现路由的规则策略,并且全链路需要传递版本信息
以如下调用链为例,两个调用处做修改,一处为网关,一处为服务间调用,使用 header 加 version 的方式,其余方式同理
由于需要对服务器进行标记版本号,在此介绍基于 consul 的配置,需要在服务的配置文件中加如下配置
spring.cloud.consul.discovery.tags=version=V1
增加后,在 consul 控制台中能看到如下配置
服务发现即可获取到此配置
服务发现其实可以使用 spring.cloud.consul.discovery.server-list-query-tags 配置来发现指定标记的服务,但是不利于动态修改,不使用此方法
如果 gateway 集成了 ribbon,则服务调用负载均衡使用的时 ribbon,否则使用的是 loadbalancer,可通过如下配置修改,默认为 true
spring.cloud.loadbalancer.ribbon.enabled=false
下面已两种方式分别介绍
gateway + ribbon 路由调用链
基于 ribbon 的负载均衡默认网关拦截器为 org.springframework.cloud.gateway.filter.LoadBalancerClientFilter 我们可以重写 choose( ServerWebExchange exchange) 方法,来支持拦截请求头,做规则逻辑,见 com.baidb.gateway.ribbon.filter.GrayLoadBalancerClientFilter 类
ribbon 的负载均衡规则需要支持服务选择,在此通过继承 com.netflix.loadbalancer.RoundRobinRule 实现轮询规则,见 com.baidb.gateway.ribbon.rule.RibbonServerDiscoveryRule 类
配置类使过滤器和规则生效,见 com.baidb.gateway.ribbon.configuration.RibbonConfiguration 类
gateway + loadbalancer 调用链
基于 loadbalancer 的默认网关拦截器为 org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter 我们可以重写此类支持拦截请求头,见 com.baidb.gateway.reactive.filter.GrayReactiveLoadBalancerClientFilter 类,主要重写 createRequest() 方法,将请求头传递到 loadbalancer
默认的 loadbalancer 实现为 org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer,仿照此类,我们实现见 com.baidb.gateway.reactive.loadbalancer.GrayReactiveRoundRobinLoadBalancer 类,主要方法 processInstanceResponse()
配置类使过滤器和负载均衡器生效,见 com.baidb.gateway.reactive.configuration.ReactiveLoadBanlancerConfiguration 类
openfeign + ribbon 服务间调用链
跟据调用链,我们需要在 openfeign 请求时请求头增加 version,并且在调用 IRule 时,根据上下文 version,选择服务,上下文绑定参数可以使用 java.lang.InheritableThreadLocal 进行绑定参数
首先需要使用 aop 在 openfeign 调用前,绑定参数,请求后,清除参数,见 com.baidb.service2.aspect.FeignRibbonFilterInterceptor 类
openfeign 请求时,在请求头增加 version,见 com.baidb.service2.feign.FeignHeadersInterceptor 类
重写 IRule 实现服务选择,见 com.baidb.service2.ribbon.RibbonServerDiscoveryRule 类
配置类见 com.baidb.service2.configuration.OpenFeignConfiguration 类和 com.baidb.service2.configuration.OpenFeignClientsConfiguration 类
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。