和其他互联网产品一样,NOS作为面向开发者(同时也直面用户请求)的产品,技术上的短板和流程上的缺陷随着越来越多产品的接入及产品自身的发展壮大不断凸显。
2013年,IM大战爆发,微信、来往之外,网易和电信公司联合推出易信,希望能在IM领域占得一亩三分地。技术上,易信UGC数据(语音、图片、视频等)的上传、存储、访问和处理基本全部使用NOS。NOS和其他网易云计算服务保障了易信产品在短期内快速发布上线。
但是上线之后的大规模推广给NOS系统带来了数十倍于往常的压力,UGC产品带来的线上增量是NOS团队未曾预料到的。
2013年5月的一天,阳光明媚一如既往,但就在16:20,NOS团队的上空飘来了一片阴云:NOS一台服务器意外挂掉,随后产品方反馈NOS服务很慢,团队排查发现此时NosProxy(NOS对外业务逻辑服务模块)使用的servlet容器Tomcat的连接数从往常的100、200上升到5000以上,对于Tomcat 这样的线程并发模型服务器(Thread Based concurrey Servlet),底层需要一个线程处理一个用户请求,而依赖组件的过载和超时的不合理设置直接导致了处理线程一直被后端依赖组件block。16:32,连接数再一次恶化,NOS对外提供的所有接口和服务陆陆续续不可用,用户请求的不断到达和后端依赖模块的过载,直接导致系统发生了雪崩效应。事态严重,NOS团队立即对线上服务模块进行重启并启动扩容计划,开始调集公司力量增加新服务器进行线上扩容。
此时丁老板办公室外面的易信团队异常骚动,问候NOS爹娘的声音此起彼伏。到了下午17时多,NOS又一次出现故障,新机器还没ready,团队所能做的就是重启重启再重启,突然,NOS负责人后面出现了一个高大而又陌生的身影,丁老板穿着拖鞋下来了,直接彪了一句“Tomcat怎么能这么用”(你没听错,丁老板是技术出身的)。记忆中,这是我们头一次离老板这么近,近在咫尺,丁老板在背后看着我们处理线上问题,更多的细节伴随着颤抖着的小手敲着键盘的声响已经记不太清了。
成长的代价很沉重,但收获是沉甸甸的。此次重大事故后,团队进行了全方位的总结,技术方面的改进很多,主要包括:
服务拆分:子系统过载会级连导致整个系统的过载,对关键服务模块进行了拆分和隔离。
过载保护:对所有子系统的调用设置合理的超时,避免持续等待,并且进行了完善异常验证测试。
尽力而为:子系统过载服务不过来的时候直接拒绝服务,尽力而为,并且拒绝做无用功(客户端已经超时的请求直接丢弃)。
高可用:避免系统单点,使用Nginx健康检查、VIP、自动切换脚本等机制自动屏蔽故障节点,保障线上服务持续可用。
故障隔离:对图片、上传下载服务器进行物理机器的隔离,物理隔离代价较大,在实践上还要在逻辑上对不同业务进行一定隔离,比如进程隔离、业务隔离等等,避免一个篮子里所有的鸡蛋都出问题。
三、快速发展
技术和构架上的改进基本能够保障系统宏观上跟得上业务的发展。而如何在产品快速发展过程中保持持续稳定,是我们这5年来遇到的一个很大的难题。
首先看一个概念,对于云服务而言,评估一个服务是否稳定有一个很重要指标,即可用性或者说可用率,该指标具体量化了系统或者服务的稳定性特性,如表1所示。
表1 云服务可用率指标
详细可参看:如何打造高可用系统(复制到浏览器查看:bitstech.net/2015/12/18/high-availablity-system/)。
在NOS产品的不断发展中,除了需要持续维护系统稳定的运行,还需要不断开发新功能,并进行构架的调整。如何在大大小小的关节点和振荡期持续对外稳定输出服务,维持高水准的稳定性和可用性? 这个问题的解决,需要长时间的积累以及团队的坚持履行,甚至涉及到团队文化的建设,远比绝大部分技术上的调整艰难得多。下面我们具体来看NOS团队在这方面的实践经验和取得的成绩。
表2为团队在高速发展的2年中记录的NOS实际线上可用率数据。
表2 NOS可用率提升历程