灰度发布
背景
由于公司产品更新迭代快,每完成一部分新功能都要能及时上线给客户使用,但是上线过程中难免会出现一些问题,前期客户量不多的情况下影响不大,但到今年开始客户量剧增,只要服务一出现问题就会有各种投诉电话打到公司,于是从今年四月份开始准备调整服务发布流程为灰度发布,中间做了很多方案调整,一直到 7 月底才完成所有调整,特此简单记录下。
原有技术架构
公司服务采用前后端分离,后端使用 Java,前端使用 nodeJs,后端为 SpringBoot 微服务架构,不同功能模块相互分离,服务发现与注册使用 zookeeper,消息队列使用 Rabbitmq,服务间调用使用 RPC 协议,缓存使用 Redis,数据库采用的是 MySQL,所有服务都是部署在阿里云上,原有拓扑图如下:
客户端访问应用服务会先通过负载均衡,负载均衡将流量进行分配到各应用服务器,各应用服务器进行业务处理再将结果返回给客户端。
灰度发布调整
在进行灰度发布调整前,和开发进行讨论了多次,最后确认了方案如下:
将整体服务分为两部分,命名为 A、B区域,客户端访问还是会通过负载均衡进行流量分发,但是此时负载均衡使用的是四层转发到两套 nginx 上,A、B区域连接同一个数据库和缓存,但是 zookeeper 和 Rabbitmq 为单独两套服务。
原因
- 为什么使用负载均衡加 nginx
因为我们所有服务都是部署在阿里云上,阿里云上的 api 比较完善,采用负载均衡是为了作为一个开关使用,当进行发布时可以直接通过 api 将流量直接切换到对应环境而不用修改 nginx 对应配置 - 为什么使用同一套缓存和数据库
先说数据库,如果采用两套数据库会涉及到数据同步问题,这样的工作量比较大,使用一套数据库只会涉及到增加序列化问题,这个只要增加 sql 审计即可解决。
缓存之前有讨论过使用两套,但是系统中部分功能如登陆态、认证状态都是暂存缓存中,使用两套会影响功能使用 - zookeeper 和 rabbitmq 使用两套
因为服务间的调用时使用 RPC 进行的,而且服务需要注册到 zookeeper 上,如果使用一个 zookeeper 就会涉及到调用时会有可能 A 区域的服务调用到 B 区域
使用两套 rabbitmq 因为 zookeeper 使用了两套,而服务进行消费消息时也是通过 zookeeper 进行调度的,因此也使用两套
灰度发布流程
- 通过 api 切换对应环境,只提供 A 环境给客户端进行访问
- 升级 B 环境并进行测试
- 通过 api 切换对应环境,只提供 B 环境给客户端进行访问
- 升级 A 环境
- 通过 api 切换对应环境,提供 A、B 环境同时提供服务
遇到的问题
- 测试问题
由于域名只有一套,所以在测试时需要内部自建 DNS 解析以提供 公司内部测试时访问已升级的环境 - 定时任务
由于系统定时任务时依靠 zookeeper 进行调度的,但是 zookeeper 有两套,这就会出现定时任务会重复执行两次的情况,严重影响业务如客户充值 100 元,但定时任务在入账时入了两次,导致客户账上有 200 元,这个问题是通过开发手段,修改开发配置使定时任务只连接一套 zookeeper。 - 高并发问题
由于之前一直采用的是阿里云负载均衡进行流量分发,没有考虑过高并发问题,这次切换成 nginx 之后,很快就出现了并发量较大导致服务不肯用的情况,这里做的操作就是优化 nginx 配置
总结
这次调整断断续续做了三个月,期间也是出了很多问题,最后都逐个解决了,收获还是挺大的:
- 做大调整时需要和开发测试进行详细的沟通
- 要考虑到测试环境和生产环境的差异
- 做好失败后的挽救措施准备
- 多参考成熟的方案结合实际情况进行改善