蓝绿部署:写给初学者的通俗解释
前两天帮朋友更新一个小网站,用的还是最原始的套路:ssh 上去,停服务,换新包,再启动,中间一分多钟用户全是 502。朋友问我有没有优雅点的办法,我说那你得了解一下蓝绿部署。这玩意儿概念简单到离谱,但真到用的时候,坑也不少……
什么是蓝绿部署
说白了就一句话:准备两套一模一样的环境,一套叫蓝,一套叫绿。同一时刻只有一套对外服务,另一套闲着。要发新版本的时候,你把新代码部署到闲着的那套上,自己先测试确认没问题,然后把流量整体切过去。切完之后,原来那套就变成了闲着的那套,留着回滚用。
举个例子,现在线上跑的是蓝环境(v1.0),用户所有请求都打到蓝上。你要发布 v1.1,就把 v1.1 部署到绿环境,这时候用户根本看不到绿的存在。你在绿环境里点一圈,确认功能正常,然后改一条路由规则,让流量全部指向绿。整个过程用户基本无感,因为切换的那个瞬间,服务本身从来没停过。
为什么不直接在原环境上更新
有人会问,我直接停掉老版本换新的不行吗?行,但有几个绕不开的坑:
- 重启的那几秒到几十秒,请求会失败;
- 新版本如果有问题,回滚得重新部署老版本,越急越慢;
- 启动之后才发现配置写错了、依赖连不上之类的,用户体验已经受损了。
蓝绿部署的本质,就是把「部署」和「切换」这两件事拆开。部署可以在后台慢慢做、慢慢验证,切换本身只是改一条路由规则,一秒钟都不要。出问题了再切回来,也是一秒钟的事。
实际怎么操作
小项目不用上 K8s 那些大家伙,下面是我自己实测过的一套最简做法:两套服务 + nginx 的 upstream。
upstream app {
server 10.0.0.1:8000; # 当前是蓝
# server 10.0.0.2:8000; # 绿,平时注释掉
}
发布的时候,把注释换一下:
upstream app {
# server 10.0.0.1:8000;
server 10.0.0.2:8000;
}
然后执行 nginx -s reload,流量就整体切过去了。reload 是平滑重载,不会断已有连接,这一点很关键。想回滚就把配置改回来再 reload 一次,前后几秒钟的事。如果你用 docker-compose,那就是两个 compose 项目,名字上区分 blue/green,配合 nginx 或者 traefik 做切换,思路完全一样。
几个容易忽略的坑
数据库。 这是最大的坑。蓝绿部署默认两套环境共用一个数据库,所以蓝还没切走的时候,会出现「新代码 + 老表结构」一起跑的情况。这就要求迁移尽量向后兼容,别一上来就删列、改类型。正确姿势一般是先加新列,等流量切完、稳定运行了,再回头删老列。
会话和缓存。 如果 session 存在本机内存里,切到绿环境用户就全掉登录了。要么把 session 放到 redis 这类共享存储,要么干脆用无状态的 token。
切换不是瞬间完成的。 已经建立的长连接、正在处理的请求,还得等它们自己跑完。所以切完之后别急着动蓝环境,观察几分钟日志,确认没报错再说。老环境也别急着删,留个一两天,万一要回滚呢,删了可就真没了……
什么时候没必要用
说实话,个人博客、一周没几个人访问的内部工具,直接停机更新也无所谓,那几分钟没人在意。蓝绿部署的代价很直白:资源翻倍,两套环境都得花钱、都得维护。流量小、能容忍短暂停机的场景,先解决「有没有自动化部署脚本」的问题,比上蓝绿更有意义。
等哪天你真的被一次失败的发布搞得焦头烂额,回滚花了半小时,那时候再上蓝绿,你会觉得这玩意儿是真香。
小结
蓝绿部署没有什么高科技,核心思想就一句话:永远保留一套能用的环境,发布靠切换,不靠重启。先在自己的小项目上完整练一次,理解了切换这个动作,以后再碰到云上的负载均衡、K8s 的滚动更新,无非是同一个思路的不同实现罢了。没准儿哪天你就用上了。
评论
还没有评论。
发表评论
提交后评论将经过自动审核,审核通过后公开展示。