前几天遇到一个很奇怪的问题,cgi发布后,发布webserver一台接着一台挂到,top看系统负载并不是特别高,然后netstat -ant了一下,发现很多CLOSE_WAIT状态,难道是连接数超上限了,就看了一下/proc/net/sockstat,果然吓了一跳,连接数超过10W,难怪系统会挂掉,连接数太多,很多cgi被挂着系统已经处理不过来了,看来架构是有问题的。说下系统的架构吧。
由于当时开发的比较敏捷,WEB层是直接连数据层的(当然不是裸DB,外面有一层接入cache server),初期没有问题,但随着在线用户数增涨,web server和cache都要扩容,这时直接就有问题了。由于web server使用fcgi方式处理,fcgi与后端的cache建立长连接,当web server到100台,每台机400个进程,cache server到50台时,就出现一个web server上有400*50=2W连接,每台cache server上4W连接,如下所示。
user_00@server:~> cat /proc/net/sockstat sockets: used 52288 TCP: inuse 51877 orphan 21 tw 10288 alloc 51877 mem 34506 UDP: inuse 7 RAW: inuse 0 FRAG: inuse 0 memory 0
当然这个时候还不会成为瓶颈,但如果再扩容cache server的话,问题就会更加的放大了,那怎么解决这个问题呢。有一个短期的方案和长期的方案。
1.短期方案
合理配置web server上的进程数,首先统计所有fcgi大置分配的比例(根据用户行为分析或用webserver的访问统计功能),合理的分配fcgi,减少fcgi的数量,后来调整发现单机只要用200个进程就可以满足当前的接入,并且每天在线最高时还有70%的idle,所以这个方案可以短期时满足在线人数增长的需要。
另一个方案是用短连接,这种方案虽然可以规避连接数的问题,但是会导致接入能力和处理能力下降。
2.长期方案
在web server和cache中加一层logicserver,使cgi只负责接入,业务逻辑的处理完全交给logicserver处理,这样单机webserver接入能力会上升,负载也会变低,而logicserver只处理核心业务逻辑,处理能力是很强的,以之前的规模,100台webserver完全成分成80台webserver+20台logicserver,logic server可以开200个处理进程,这样webserver只要200+20=4K连接,而每台logicserver和cache也只200*50=4W连接,当然logic server可能不需要200个处理进程就可以搞定,logicserver的可控制性更强一些。这样即使cache再扩容,基本也可以满足。
用logicserver好处比较多,现有的webserver中,如果cgi处理太多的业务逻辑或频繁与后台数据层交互时,会使系统性能很低,有同事做过测试,webserver+logicserver+cache模型要比webserver+cache模型节省大概2/3的机器数。