这几天xx病毒在成都又开始抬头了。响应国家号召,成都市民从9月1日起开始居家,并开始了三天三检。相信大家已经知道了,就是这边的核酸登记系统崩溃了。
这个事情随着人们的脚力逐渐耗尽,开始在网上逐渐蔓延,进而算是一个不大不小的公共事件。
作为一名普通的参与者,9月2日下午我是排队排了将近3个小时才成功做了核酸。整个排队队伍其实不太长,但听到前面的人说一个人有时候都要十分钟才能提交成功,轮到我了,我特别留意了下这个核算系统的卡点,发现扫描健康码一般挺快,但到把你提交到批次的提交操作则卡到爆,等一会就报一个错,然后工作人员再重复点击提交,就这么一直失败提交失败提交,屡战屡败若干个来回,偶尔一次成功了,大家都欣喜若狂长吁短叹。
这个事情在网络上引起了不小的关注,特别是技术圈子大家本能的开始寻找可能的原因。
首先大家确定是东软开发的这个核酸系统,并且是9月1日切换到这个新的核酸系统,至于为什么从老的省系统切换到新的东软的这个系统咱也搞不清楚。
接下来我们就仅仅分析一下这个”事故“(姑且定义为事故,如言重请见谅)产生的可能的原因。
容量评估
我们就从小区这个基本的核酸场景开始分析。
我们从成都市发改委的官网上查到2021年成都市常住人口为2119万,这里我们姑且就以这个为2022年的常住人口。
2119万人口,我们假定一个小区2119人,每个小区有一个核酸检测点,那么就是1万个核酸检测点,也就可以认为东软这个核酸系统最高并发量约为1万。划重点,最高并发量为:1万。
容量评估出来以后,我们就开始分析可能发生事故的卡点。
可能的架构
以本人对于类似项目的判断,我简单推测了下这个系统极有可能的架构。有了这个基本的架构假设后我们就开始分析每一层。
可能的卡点
android客户端
android客户端会导致这次事故吗?显然不会,经过本人两次核酸时特意观察,发现android客户端本身并没有什么问题。因为它可以在每次请求后都会弹出一个框来响应,而且工作人员们台子上放了好几部手机看起来都非常丝滑。
nginx
nginx会出现问题吗?可能会。前面我们已经对并发量做了评估是1万,然而nginx的底层是通过epoll、select这种nio来实现的,epoll这个就非常依赖文件句柄量,linux默认的文件句柄是1024。这个数量能不能满足1万并发呢?存疑;另外就是TCP最大连接数(somaxconn)这个参数也要调整到1万。
那东软这个核酸系统有没有这样调整呢?不得而知。所以nginx出现瓶颈是可能的。
tomcat
我记得tomcat默认的最大线程数是200个,如果在后端服务这一层没有做很多的扩容,那么tomcat这一层出现问题也是有可能的。
tomcat的两个参数:
maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200 acceptCount:当tomcat起动的线程数达到最大时,接受排队的请求个数,默认值为100。
一个1万并发容量的系统,只有200个tomcat线程能力肯定是不够的,这里需要启动多个tomcat实例来支撑这1万并发。我们以最保险的容量来预估则需要10000/200=50,则需要50个tomcat实例来支撑成都这次全员核酸,这样就比较保险。
很明显,经过我们的分析tomcat后端服务层也是有可能出现瓶颈的。
数据库
我们猜想这个核酸系统用的就是mysql,并且极有可能是单库单表。一般低并发数据量小的场景,我们会用2核4G,4核8G就够了,但遇到1万这种并发量显然是不够的,这时候就得上更高配置8核16G,这样的配置每秒大概可以抗的并发量大概就是在几千这数量级,这个1万的并发量姑且能够顶得住。但其实也够呛。另外就是数据量,假定做一次核酸需要写入1500万条数据,那么如果mysql数据库设计的不够简单,如果你冗余了较多字段,那么这个数据量在单库单表的情况下也是可能会出现问题的,这个取决于具体东软的数据库表是怎么设计的了。
所以数据库也是有可能产生瓶颈的。
我们把系统的每一层都分析了一遍,发现除了客户端,每一层都可能导致本次事故。
其实还有一个我们没有分析,那就是代码的质量。
代码质量
通过大家的观察,发现这个核酸系统它是一会卡了,一会又不卡了,仿佛人多的时候就卡了,人少了又恢复了。什么样的代码会导致这样的现象产生呢?我们知道java代码在fullgc的时候,会STW,stop the world,这时候会把用户线程都挂起,那么在核酸高并发的情况下发生STW会发生咩事呢?就是卡。等到垃圾回收完了,系统又会好一会,然后下一步垃圾又填满了堆,这时候又卡了。所以这次事故也有可能是代码质量导致的。如果东软这个系统的垃圾回收器用的是CMS(老年代),那么如果恰好程序代码有一些大对象导致JVM在高并发时来不及在新生代回收,并且放不下这个对象,则会直接被转到老年代,进而导致老年代在极短时间内达到阈值从而触发fullgc。这样的代码也许在人少的时候表现的不够明显,但高并发势必会卡到爆。
所以代码质量也可能导致这个事故发生。
网络原因
网络原因会导致本次系列事故?不太可能。三番五次的卡顿和崩溃显然不像是网络原因,如果只出现一次那还有可能是带宽的原因。通信网络基础能力还是很强的,支撑了多少年了,你什么时候听说过双11因为网络而导致故障?很少。还有一些工作人员把手机举的天高,这个也是低估了基站的能力了。一个小区排队做核酸的才多少人,除非几万人的聚集(比如演唱会、球赛)才会出现基站瓶颈,这时候才会出现通讯车来保驾护航。
综上所述,我们认为nginx、tomcat、数据库、代码质量都可能会造成本次事故,甚至是多点原因导致本次事故。至于网络原因,我们认为可能性是极低的。