基于阿里云SLB的用户无感滚动发布方案
滚动发布
滚动发布是最常见的一种发布模式,基本在大厂都是标配。大厂光一个应用就可能有几百几千台机器,如果没有滚动发布的能力,几百几千台机器一起同时发,就会导致用户感知长时间的访问失败,服务不可用,严重影响用户的体验,这在大厂是一定不允许的。
所以滚动发布就是一种比较优雅的发布方式,可以做成分批发布的方式。我们可以将所有的ECS机器分割成多个批次,每个批次间是顺序执行发布,而在一个批次中的所有机器都是同时并行发布,每个批次在发布之前会将访问的流量切走,即做一个「下线」的动作,等到该批次全部发布完成后,再「上线」,流量就再回流到已发布完成的机器上。就这样每个批次依次滚动发布完成。
【图】日常流量是均匀的分布在两个批次之间
【图】第一批次发布前先将50%的流量切到第二批次上,这样第二批次就承载了全部100%的流量。这里得注意容量评估,避免流量过大,导致将服务器压垮。
【图】第一批次发布完,将流量全部回切到第一批次,然后再滚动将第二批次系统开始继续发布。
虽然我所在的创业公司还小,但是追求还是很高的,即使后端机器不多,还是需要在整个发布流程中尽量减少对于用户的打扰,避免服务存在不可用的情况。下面就是我们的实践。
基本环境
- 负载均衡能力:阿里云SLB
- 后端服务部署:阿里云ECS
- 端口服务转发:Nginx
【图】部署图
实现「下线」和「上线」
阿里云SLB本身具备对于挂载服务器服务是否可用的健康探测的机制,可以秒级的不断向已挂载的所有服务器发起探测请求,如果连续多秒探测不可用,则SLB就会自动将流量切走;类似的,当后台服务恢复可用后,SLB探测到连续多秒可用时候,就会自动按照之前设置的流量权重将流量再回切。所以就自然而然的想到要实现上线和下线,可以通过探测路径的返回值来做文章。
如上图所示,我们可以在SLB配置中,设置健康检查的方法和路径,即使用HEAD请求的方式请求/nginx-status路径,如果返回HTTP CODE 2XX 3XX那都表示正常状态码。其他状态码4XX,5XX都是当做服务器异常处理。健康检查间隔会按照2秒一次touch的频率,如果连续两次touch都是异常状态码,则直接返回失败。如果连续三次touch都是正常状态码,则表示服务器已经达到可服务状态。
这样我们就可以在服务器上配置对应nginx配置,让/nginx-status的URL请求派发给到一个本地文件,「下线」过程即将该文件删除,那么请求就会立刻返回404,4S之后该实例就被从SLB摘除;与之对应,上线即将该文件恢复,SLB会在连续3次正常返回的touch后,将该机器再挂载回来。
所以对应的应用启停的脚本就如下:
# 下线操作,删除对应的本地文件
rm -rf /home/admin/nginx-status
# 按理是4S,此时留一些buffer,即6秒之后,SLB一定以及探测该服务器服务不可用,将至摘除
sleep 6
# 上线操作,恢复对应的本地文件
touch /home/admin/nginx-staus
# 6秒后,SLB探测到服务可用,将流量恢复
sleep 6
Nginx的对应配置:
http {
server {
listen 80;
server_name localhost default;
location /nginx-status {
root /home/admin;
}
}
这样就能够保证下线机器已经无生产流量,可以正常发布;发布完成后,在将流量回切,继续下一批服务器的串行发布。
引用文章: