猪八戒网随着业务访问量的直线增长,用户增长达到一定规模后,同时面临着高并发业务和海量数据的挑战,传统单机房在服务器容量上存在瓶颈,而且在一些不可预知场景下,导致整个网站出现故障,例如机房断电、火灾等这些不可抗拒因素都会导致所有服务器出现宕机从而导致业务瘫痪,即使有备份,恢复业务花费的时间也比较长。所以公司根据实际业务情况选择了同城双活流量高可用架构,当然还有两地三中心、异地多活等方案。
本文主要基于同城双活流量叙述猪八戒网这16年的双活流量架构演进之路。
初期
2014年前猪八戒网的服务器都是托管于传统IDC机房,虽然业务应用、基础组件、数据库等都设计了高可用模式,但是避免不了机房宕机导致整个网站出现故障的问题。如图1:
图1:单点机房
直到2015年初的时候,由于机房人员日常维护的时候,不小心把我们的核心交换机网线碰松了,然后导致整个猪八戒网打不开,我们通过各种排错才定位到这个问题,经过此事件后,上层领导高度重视网站的可用性问题,为了解决机房不可控的因素,所以2015年中旬开始建设备用机房,解决机房单点问题。(注:当时基础组件及业务应用不具备双活条件,只支持主备架构模式)如图2。
优点:
- 主机房发生故障时,通过DNS解析到备用机房,解决机房单点故障问题;
- 主备架构模式简单,持久化数据异步同步到备用机房,不用考虑脑裂问题。
缺点:由于备用机房平时处于空闲状态,造成大量资源浪费问题。
图2:同城主备
中期
经过1-2年的迭代,大概在2017年的时候,随着基础组件的升级改造,例如:数据库、缓存、队列、对象存储、配置中心等都支持了双活流量架构模式,然后业务应用纷纷改造适配双活流量架构模式。终于我们可以把网站域名同时解析到2个机房了。如图3:
图3:同城双活(基于DNS的双活)
基于DNS切换流量模式还是有瑕疵的,在猪八戒网运行了3年左右,在此期间多次出现某机房不稳定事件进行全局流量切换,主要问题体现在某些DNS服务器不跟着协议走,导致切换流量生效时间慢,流量切换不彻底的问题。
提示:一般情况我们遇到的单个机房故障,主要体现在基础组件、业务大面积瘫痪等问题上,不涉及到入网流量的问题,假如真的是入网流量异常了,也只有等DNS解析生效了。
鉴于以上遇到的问题,我们换个思路解决如何快速切换流量,最终方案是在HTTPS层的Nginx(ngx_lua)代理服务器实现快速动态分流的功能(项目为:Signpost),为什么采用ngx_lua?因为ngx_lua在猪八戒网稳定运行5年+,不管是开发效率及性能,Lua有着天然的优势,语言表达能力也更强,而且ngx_lua是同步非阻塞(100% non-blocking)的,再次感谢章亦春 (agentzh)大佬的开源作品lua-nginx-module。如图4:
图4:HTTPS代理层分流
如何基于ngx_lua设计动态分流功能呢?简单通俗一点就是如何快速动态切换Nginx的upstream进行分流而不执行nginx reload。关于Upstream是如何动态生成的?请查阅上篇:《
猪八戒网Nginx的动态服务发现演进之路》
首先管理人员配置分流策略到CMDB系统中,然后CMDB同步到Redis缓存,当用户请求时,Nginx接受到请求后,先从worker缓存获取分流策略,如果worker缓存没有,就到lua_shared_dict缓存获取,如果lua_shared_dict也没有,那就到Redis中读取,然后依次缓存,根据匹配的分流策略执行指令。假如没有获取到分流策略,那就按照默认策略分流。如图5:
图5:动态切换Upstream架构
为什么会有三级缓存?因为worker缓存支持数据结构缓存,而且没有锁竞争,lua_shared_dict缓存有锁竞争,不支持数据结构存储,Redis缓存需要TCP连接消耗,最终都是为了性能!
现在
经历了数月的开发及基础架构改造,终于在2020年9月初,基于HTTPS层的Nginx(ngx_lua)快速动态分流的功能成功上线了,主要支持了全局模式、单域名模式的流量切换,还额外支持了域名动态HTTP/HTTPS协议切换。如图6 - 9:
图6:同城双活(基于NGX_LUA的Signpost)
图7:双活流量控制台
图8:单域名切换功能
图9:单域名切换日志
最后,关于Signpost软件的主要特性,支持多活流量管理,根据不同维度进行分流,例如:IP段、地区、Cookie、浏览器、GET参数等,流量切换可以精确到秒级,而且全程用户零感知。
原文链接:
https://mp.weixin.qq.com/s/6crbquRkYZPiICVdzVqkxQ