西安一码通系统故障BUG分析及解决建议!
冬日的古城长安,防疫的形势严峻,两千精英共驰援,八方援军助检测。
为了有效控制疫情,西安市已启动了多轮次的全员核酸检测工作。12月20日在广泛要求48小时有效核酸及连续多日核酸检测登记录入的特殊情况下,有着金边护身符美誉的“西安一码通”出现了系统故障。
一时间,环普美林成了舆论的关注点。多位IT行业的雲著君走在了关切咨询的最前沿。针对“西安一码通”系统故障问题,雲著君在业主范围内开展了一定的技术交流,希望通过小区特有的IT技术优势,提出一些合理的意见建议。
最终为“西安一码通”的稳定运行贡献出雲著力量。
1. 健康码无法打开,页面点击二维码后出现空白。
2. 部分情况出现502bad Gateway。
3. 核酸报告系统出现问题,结果无法显示。
4. 恢复的过程中出现中国电信手机网络可以打开健康码,中国移动不可以的情况。
图1 无法打开的一码通
图2 核酸检测证明与疫苗接种情况无法显示
对于“西安一码通”出现的故障问题,10余位来自鹅厂、华为、中兴、ICT数据分析的雲著君从前端、后端、测试问题进行了原因分析。
(一)主要问题
1.限流问题:市民在长时间无法刷出健康码的情况下,多次退出刷新重试,新的流量到达服务器,导致服务器压力变大、承受负载增加,说明“西安一码通”系统没有做好限流措施。
2. 服务器问题:无论是企业和个人在租用服务器的时候都会受到峰值承受限制的,一旦超过服务器的承受能力,就会导致服务器瘫痪,应用程序暂停,网站无法访问。服务器是有峰值限制的,不可能承受无上限的并发能力。而造成服务器瘫痪的原因就是在同一段时间内,访问人数多,造成高流量的突进,超出了服务器的承受范围。
3. 架构问题:“西安一码通”功能影响“核酸检测”服务,说明模块间从界面到数据调用互相影响,可能不是微服务架构。
4. 性能过载:典型的性能过载场景,不论内部根因是数据库瓶颈点,还是网络链接数瓶颈点等等,外因都是因为过载导致。
5. 场景问题:
大数据查询下载的时候,一个线程占用资源过多,导致其他服务等待乃至个人电子码里面核酸的信息不显示了。所以估计“西安一码通”是个门户,数据甚至“卡片”都是从各子系统引过来的服务器挂死宕机的情况;
猜测上班高峰期大家都在访问同一个服务导致服务器瞬时访问流量飙升,数据库性能也跟不上,最终整个“西安一码通”服务挂了,可能之前设计的时候没有考虑过这种场景。
6. 设计漏洞:没有考虑高流量高负载的情况,导致测试不充分;产品设计未考虑千万级的并发访问,交付前未进行同等级的压力测试。
7. 压力测试:在市民长时间无法看到健康码的情况下,多次退出刷新重试,新的流量到达服务器,导致服务器压力变大、承受负载增加。说明压力测试不够。
(二)其他问题
1. 初步推测是nginx后台的应用服务器高并发下挂掉,怀疑是缓存击穿,导致后台数据库响应时间变长,前台长时间无法响应。
2. 看官方报道,说网关流量太大导致系统故障,证实了负载均衡出现问题,传统在线系统一般采用lvs+nginx+动态DNS,本次系统初步推测没有使用动态DNS,导致单机网卡被打爆;恢复时推测使用了新的网关机器,等待新dns生效耗费大量时间。
3. 对于中国电信网络信号可以打开,中国移动网络信号无法打开的情况,不同的运营商走的DNS系统不同,因为“西安一码通”系统电信公司有参与,所以DNS指向新的ip生效最快。
4. 该问题反应出在目前国内外疫情仍然严重的背景下,““西安一码通””相关系统的灾备建设仍不充分。未进行故障隔离和流控处理,运维预案和弹性伸缩能力不足,SLA处理时长超过12H,各个服务厂商只能处理本服务问题,联合定位协调不及时。
5. 处理器可靠性测试包括测试标准可能存在问题,用于计算的CPU部分是否预留了合理的Margin。
6. 倾向于是硬件负载均衡器F5故障,不知道有没有gateway-service,在gw做限流,当然应该在高防的后面WAF做一下安全策略来保证系统的高可用HA,另外早高峰可以采用MQ进行异步消峰处理。(猜测没有gateway,若有BFF层,也不会这么惨)。
(一)产品建议
进行业务剥离将小程序内业务关联度比较高的模块独立化。
(二)系统建议
1. 快速响应短期建议:
(1)页面优化:友好提醒用户耐心等待 ; 当出现不能显示查询结果的时候,为避免社会恐慌和公众猜测,应当在页面做出友好提示为宜,而不是“繁忙、无响应”等。
(2)访问节流:
短时间内多次请求可做防抖机制;
核酸结果是24小时(或更长或更短)内不变,建议做缓存机制,24小时候间隔后再次访问强制刷新,接口可带时间戳参数;
非关键渲染数据延迟请求,即发起一个聚合接口请求来获取主体模块的数据,而非主体模块的数据则从另一个接口获取,通过拆分的手段来降低主接口的调用时延;
接口聚合,请求合并,减少并发;
减少接口通讯数据,传输的数据量越多,线程间通信的耗时越长,渲染速度就越慢;
剥离并建立异步无关联性并发请求;
2. 项目稳定长期建议:
(1)业务抽象,模块剥离,独立业务模型,行成高内聚低耦合的可扩展性
产品;
(2)数据模型,尽可能结构关系单一,快速响应回调;
(3)接口隔离,多个请求间单一职责;
(4)微前端搭建多个模块,行成模块隔离;独立部署,分开运营;
(5)沉淀组件并复用,减少项目体积;
(6)建立中台,减少直接请求后台数据;
(7)应用层数据加diff算法,去掉不必要且无改动的数据渲染,加快渲染时间。
(8)崩溃预警,可让相关开发人员快速上线响应。
3. 系统设计建议:
(1)架构设计:业务抽象,模块剥离,独立业务模型、数据模型,尽可能结构关系单一,接口隔离独立部署,分开运营。
(2)云原生:应该尽早做微服务化改造,技术中台,服务网格化,云原生弹性伸缩(K8S),尽快实现抽象,沉淀,复用,提高系统SLA,由于“西安一码通”信息的特殊性建议使用私有云。
(3)中间件选型:数据库可以采用TiDB这种分布式数据库,完美兼容mysql协议,可以扛住大并发,缓存可以选用redis cluster需要做到高可用。
(4)分级管理:根据业务重要性进行分级管理,核心应用和服务优先使用更好的硬件,在服务部署上进行必要的隔离,避免故障的连锁反应。低优先级的服务通过启动不同的线程或部署在不同的虚拟机上进行隔离,而高优先级的服务则需要部署在不同的物理机上。
(5)CDN缓存: 资源常用数据缓存CDN,一方面加快用户访问速度,另一方面减少后端服务器负载压力。
(6)安全提升:提升“西安一码通”系统机房安全等级,以应对各种极端情况,建议参考银行一类业务系统建设标准; 如关闭不用的端口,减少不必要的暴露。
(7)预警机制:服务可用性,磁盘空间,CPU负载,内存使用率等指标需要有及时的告警机制。
(8)网络可用性:不用运营商,不同地域网络可达性监测
4.高可用设计建议:
健康码服务是一个典型的读多写少场景。以最简易、常见的服务拓扑:客户端 -> 网关 -> 主服务 ->缓存&数据库 -> 子服务,尝试分析三高(高并发、高性能、高可用)设计的常见思路:
(1)服务、数据冗余
数据冗余:以关系数据库为例,可以读写分离。极端故障可以进行主从切换实现故障恢复;考虑“西安一码通”本身仅作为查询界面,无录入等操作,可尝试ClickHouse数据库,该数据库对于海量数据的查询性能是很优秀的,基本上千万级别查询响应仅需百毫秒以内;但是也有问题,该数据库对于更新操作不是很友好;可以在夜里低峰做批量更新。
服务冗余:包括接入网关、服务冗余。在保障服务无状态前提下,可以水平扩展服务提升服务整体吞吐能力以及降低单节点(机房)故障的影响面,在分布式服务场景下需要关注服务分片、流量分片设计、服务注册等单点问题;异地多活,可以搞多机房提高可用性。
(2)负载均衡:流控是保命手段,不是最优方案。“西安一码通”是疫情防控的重中之重。建议增加算力,提高网络能力,优化负载均衡,确保外部流量能够最优的分担到后端服务器处理。建议采用lvs+nginx+动态dns避免出现单点故障,如果不差钱可以采用F5等硬件负载;
(3)热数据缓存:避免频繁向下游取数据导致下游、数据库过载,同时提升服务响应时间。当前场景下缓存使用还需要额外关注数据一致性、缓存可用性。
一致性方面:首选需要正确的代码范式保障,其次可以采用淘汰时间 + 异步通知策略实现准实时一致性
可用性方面:类似redis cluster架构提供的分片 + 主从的分布式架构是很好的稳定性保障方案
(4)降级限流:针对服务链路各环节、节点需要评估流量阈值,针对过载流量及时限流保障服务最极端场景下的可用性。但是需要注意核心接口限流本身极大影响用户体验;对非核心功能,在过载期间可以考虑降级保障主服务可用。
(5)异步化及快速失败,异步并行读取需要的信息,对积压请求任务通过限制等待时间、甚至丢弃等快速失败的方式也是提升可用性的有效方式。
(6)DNS负载均衡,多个ip对用同一个域名,最简单是使用keepalived容灾,使某台nginx不至于被打挂而影响整个集群。
(三)测试建议
1. 添加高性能自动化测试,压力测试;在发布前做预防机制;
2. 服务演练:经常开展各种应急演练、灾备演练工作,提高问题处理效率及验证灾备系统可用性。
以上基于“西安一码通”短时期故障的前、后端原因分析和解决措施建议,仅仅是雲著君作为技术范畴的思考和探讨。
作为一个IT 工作者居多的社区,我们希望通过自身的技术建议,为"“西安一码通”"的稳定运行和持续优化建言献策,让"金边护身符"继续守护着我们的平安。
图3 奉献在疫情一线的医护工作者、秩序维护者
寒冬时节的古城虽未白雪肃穆,
共同抗疫的大旗却在空中飘扬。
在此,雲著君感谢每一位奉献在疫情一线的抗疫先行者、医护工作者、秩序维护者。
向你们问好;
向你们致敬;
向你们点赞;
我虽未能感受寒风中你躯体的冰冷,
我却亲历了你带给我们的那份平安。
愿疫情后,长安永安。