背景:约100万月活跃用户,APP版本号BUG(至少4万用户死循环訪问,堪比DDOS),修复历时7天7夜。
世界杯前夕,server拒绝訪问,线程挂死,导致大量请求拒绝訪问,少量能訪问,但訪问时间缓慢导致超时,相当于服务崩溃。
通过监听port有效的訪问连接数,最高可达1000并发。
netstat -an | grep ESTABLISHED | wc -l
訪问量已经是无法控制,仅仅能从应用入手,强制更新有bug的APP版本号,把有BUG的版本号的所有接口所有拒绝訪问,以免影响其它版本号的訪问,但效果甚微。
我怀疑此时的并发量已经远远超出现有server的压力,假设并发量超出server的承受范围,那不管怎样优化代码都是无事于补。为了验证server的极限,把全部接口都屏蔽(改成立马响应,差点儿不消耗太多的资源),经过測试发现,每开启入口,线程池立马满上,不管怎样调大入口数,最大连接数,系统文件最大打开数(Linux ulimit)等參数,到达某一瓶颈值就立马线程挂死,拒绝訪问,此时系统资源如CPU、内存、IO等系数都消耗不大,由此判断我们web容器已经到达了瓶颈。
如今仅仅剩下一个方案:扩容。扩容有两种方式,垂直扩容,横向扩容。垂直扩容相对须要时间有点长,须要安装节点,加入节点等操作,还须要測试,还会存在多种不确定风险,毕竟对现网server动手脚。横向扩容是最佳方案,由于有现成的集群server能够用(另外项目已经停止,server空暇),能够通过现网server集群的上一层做分流(F5),把一半的流量分过来新集群。于是我们又一次部署了应用到新集群server。开启分流入口,系统业务恢复,訪问正常。
好景不长,大概执行了半天时间,发现web容器线程忽然飙升到某一瓶颈值大部分挂死,拒绝訪问。我又開始怀疑难道扩容都还不能支持如今的压力,经过了强制更新和旧接口的拒绝訪问,性能消耗应该有所下降了。但发现有一个奇怪的问题,线程一開始是正常的,就是执行到某一个时间段是忽然慢慢上升,直到瓶颈值挂死,我開始怀疑应用相同存在瓶颈,開始向代码入手。由于历史原因,查看代码也是一件要命的事情,在这里消耗还不如查看执行日志,但相同是历史遗留问题,日志的错误一大堆,之前是由于不影响业务执行就无论,由于曾经系统从tomcat迁移到was的,tomcat的兼容性好,没有什么错误,可是迁移到was后就报出一大堆问题,可能是was的要求比較高,可是后来没人改改动,不影响现网执行就不理。所以如今从日志入手也是一件非常痛苦的事情,但这是没办法中的办法。把一个10M的日志文档拿下来,一个个错误排除。功夫不负有心人。最终让我发现了点苗头。发现了线程挂死的接口,后来经过了代码的排查,最终找到问题所在,是由于这个接口用到了synchronized,难怪线程会挂死,之前不会发生死锁的原因訪问量不大,如今訪问量通过推广和那个致命的BUG,不挂死才怪。
后来经过了代码的改动和完好,把全部实用到了同步的都改动了,重新启动应用打开。应用訪问正常、线程正常、可是数据量CPU消耗有点大。通过对数据库的排查,发现,是应用的业务逻辑非常多没有梳理好,SQL的很多的硬解析导致了数据库CPU消耗比較高,但这是历史遗留问题,如今一个个是非常不现实的,我们仅仅能对消耗较高的SQL进行完好。
经过几天的系统执行,相对稳定,就是数据库CPU消耗时高时地,这个应用的推广活动有关,但还不至于导致server倒闭或挂死。
系统稳定后对现网的全部日志等数据进行分析,发现我们APP的用户数增长比較快。假设安装如今的增长速度,必须还的提前申请server扩容(系统客户能够重视和给力)。
现网的系统架构是当初以一个“企业应用”建立的,还包含了很多历史遗留问题,仅仅能说too young too simple。
如今已经是百万级用户的APP了,看来,架构须要又一次设计和规划了。事实上万事具备,仅仅欠东风(客户的重视度)。我仅仅能说,系统≠软件+硬件,系统=软件+硬件+沟通+企业政策+不论什么关联因素。
世界杯前夕,server拒绝訪问,线程挂死,导致大量请求拒绝訪问,少量能訪问,但訪问时间缓慢导致超时,相当于服务崩溃。
通过监听port有效的訪问连接数,最高可达1000并发。
netstat -an | grep ESTABLISHED | wc -l
訪问量已经是无法控制,仅仅能从应用入手,强制更新有bug的APP版本号,把有BUG的版本号的所有接口所有拒绝訪问,以免影响其它版本号的訪问,但效果甚微。
我怀疑此时的并发量已经远远超出现有server的压力,假设并发量超出server的承受范围,那不管怎样优化代码都是无事于补。为了验证server的极限,把全部接口都屏蔽(改成立马响应,差点儿不消耗太多的资源),经过測试发现,每开启入口,线程池立马满上,不管怎样调大入口数,最大连接数,系统文件最大打开数(Linux ulimit)等參数,到达某一瓶颈值就立马线程挂死,拒绝訪问,此时系统资源如CPU、内存、IO等系数都消耗不大,由此判断我们web容器已经到达了瓶颈。
如今仅仅剩下一个方案:扩容。扩容有两种方式,垂直扩容,横向扩容。垂直扩容相对须要时间有点长,须要安装节点,加入节点等操作,还须要測试,还会存在多种不确定风险,毕竟对现网server动手脚。横向扩容是最佳方案,由于有现成的集群server能够用(另外项目已经停止,server空暇),能够通过现网server集群的上一层做分流(F5),把一半的流量分过来新集群。于是我们又一次部署了应用到新集群server。开启分流入口,系统业务恢复,訪问正常。
好景不长,大概执行了半天时间,发现web容器线程忽然飙升到某一瓶颈值大部分挂死,拒绝訪问。我又開始怀疑难道扩容都还不能支持如今的压力,经过了强制更新和旧接口的拒绝訪问,性能消耗应该有所下降了。但发现有一个奇怪的问题,线程一開始是正常的,就是执行到某一个时间段是忽然慢慢上升,直到瓶颈值挂死,我開始怀疑应用相同存在瓶颈,開始向代码入手。由于历史原因,查看代码也是一件要命的事情,在这里消耗还不如查看执行日志,但相同是历史遗留问题,日志的错误一大堆,之前是由于不影响业务执行就无论,由于曾经系统从tomcat迁移到was的,tomcat的兼容性好,没有什么错误,可是迁移到was后就报出一大堆问题,可能是was的要求比較高,可是后来没人改改动,不影响现网执行就不理。所以如今从日志入手也是一件非常痛苦的事情,但这是没办法中的办法。把一个10M的日志文档拿下来,一个个错误排除。功夫不负有心人。最终让我发现了点苗头。发现了线程挂死的接口,后来经过了代码的排查,最终找到问题所在,是由于这个接口用到了synchronized,难怪线程会挂死,之前不会发生死锁的原因訪问量不大,如今訪问量通过推广和那个致命的BUG,不挂死才怪。
后来经过了代码的改动和完好,把全部实用到了同步的都改动了,重新启动应用打开。应用訪问正常、线程正常、可是数据量CPU消耗有点大。通过对数据库的排查,发现,是应用的业务逻辑非常多没有梳理好,SQL的很多的硬解析导致了数据库CPU消耗比較高,但这是历史遗留问题,如今一个个是非常不现实的,我们仅仅能对消耗较高的SQL进行完好。
经过几天的系统执行,相对稳定,就是数据库CPU消耗时高时地,这个应用的推广活动有关,但还不至于导致server倒闭或挂死。
系统稳定后对现网的全部日志等数据进行分析,发现我们APP的用户数增长比較快。假设安装如今的增长速度,必须还的提前申请server扩容(系统客户能够重视和给力)。
现网的系统架构是当初以一个“企业应用”建立的,还包含了很多历史遗留问题,仅仅能说too young too simple。
如今已经是百万级用户的APP了,看来,架构须要又一次设计和规划了。事实上万事具备,仅仅欠东风(客户的重视度)。我仅仅能说,系统≠软件+硬件,系统=软件+硬件+沟通+企业政策+不论什么关联因素。