服務(wù)器高并發(fā)下的一些優(yōu)化經(jīng)驗(yàn)
技術(shù)支持服務(wù)電話(huà):15308000360 【7x24提供運(yùn)維服務(wù),解決各類(lèi)系統(tǒng)/軟硬件疑難技術(shù)問(wèn)題】
最近在高并發(fā)、較大數(shù)據(jù)的網(wǎng)站優(yōu)化上有一些心得和體會(huì),所以特寫(xiě)此文做一下總結(jié),這塊的高手就可以直接跳到文尾了哈,費(fèi)話(huà)就不多說(shuō),直接進(jìn)正文。
1.了解你的網(wǎng)站和項(xiàng)目到底有多大的流量和并發(fā)?
當(dāng)項(xiàng)目的用戶(hù)量達(dá)到一定規(guī)模以后,網(wǎng)站往往會(huì)經(jīng)常出現(xiàn)502 bad gateway(Nginx),連接超時(shí)(Apache),MYSQL拒絕連接等問(wèn)題。這個(gè)時(shí)候,一般的理解就是網(wǎng)站的訪問(wèn)量比較大,請(qǐng)求數(shù)比較高,所以服務(wù)器不堪重負(fù),開(kāi)小差去了。這個(gè)時(shí)候最快的解決辦法一般就是重啟apache,nginx或mysql,當(dāng)然這個(gè)不能解決根源,只是臨時(shí)解決一下而已。
那么,首先你應(yīng)該清楚你的網(wǎng)站的流量到底有多大?每秒的流量到底有多高?CPU占用峰值是多少?對(duì)于這個(gè)問(wèn)題,首當(dāng)其沖方案的肯定使用是監(jiān)控軟件了,這類(lèi)的監(jiān)控軟件比較多,有cacti(完全圖形化的流量監(jiān)控工具),zabbix(支持各種數(shù)據(jù)的監(jiān)控且可自己擴(kuò)展監(jiān)控模塊并集成報(bào)警功能,非常強(qiáng)大?。┧缘谝徊侥憔鸵欢ㄒ仍谒蟹?wù)器上安裝監(jiān)控客戶(hù)端,如cacti的snmp,zabbix的zabbix_client,然后搭建自己的監(jiān)控服務(wù)端。然后靜默收集數(shù)據(jù)一段時(shí)間,可以是幾天也可以是一周。然后了解服務(wù)器的峰值是多少,平均值是多少,CPU占用,內(nèi)存占用。這樣你能先做到對(duì)服務(wù)器的狀態(tài)心里有底。
2.查找高并發(fā)源泉
如果服務(wù)器一直運(yùn)行得比較正常,但突然一段時(shí)間經(jīng)常出現(xiàn)502,超時(shí),超高CPU時(shí),排除流量的超大幅度增長(zhǎng)以外的原因,那么原因就有可能是程序卡死了或服務(wù)器硬件故障。如果排除硬件故障以后這個(gè)時(shí)候最好第一步查詢(xún)MYSQL、PHP、Nginx、Apache的錯(cuò)誤日志,慢日志,定位根源文件及代碼塊,往往新功能如果沒(méi)有經(jīng)過(guò)完整的測(cè)試就上線(xiàn),就非常容易引起這類(lèi)的問(wèn)題。
比如我們的一臺(tái)線(xiàn)上服務(wù)器有段時(shí)間曾經(jīng)上線(xiàn)了一個(gè)新功能,就是要求在某代碼模塊中將MYSQL服務(wù)器地址更改為其它機(jī)房的MYSQL服務(wù)器,由于代碼沒(méi)有經(jīng)過(guò)嚴(yán)格的測(cè)試,而直接使用了MYSQL_CONNECT重新連接。在這個(gè)功能上線(xiàn)以后,服務(wù)器經(jīng)常出現(xiàn)502,超時(shí),CPU90%。后來(lái)排查時(shí)才看到這里,由于其它機(jī)房的網(wǎng)絡(luò)問(wèn)題引起MYSQL_CONNECT超慢,所以大量的MYSQL_CONNECT卡死在這里引起了阻塞。另外一個(gè)統(tǒng)計(jì)模塊的file_get_contents也是同樣的問(wèn)題,所以我們?cè)诤竺娴拈_(kāi)發(fā)中要求一定要禁止使用file_get_contents,另外MYSQL_CONNECT也要限制超時(shí)的時(shí)間。
如果程序上沒(méi)有問(wèn)題,那就要從數(shù)據(jù)庫(kù)或隊(duì)列上去查找原因了。數(shù)據(jù)庫(kù)上的問(wèn)題會(huì)非常多,比如一條沒(méi)有經(jīng)常優(yōu)化的SQL語(yǔ)句引起表的鎖死啊,MYSQL并發(fā)量達(dá)到預(yù)設(shè)峰值,表崩潰啊,等待進(jìn)程過(guò)多啊等等。
3.使用隊(duì)列和緩存
經(jīng)驗(yàn)告訴我們,隊(duì)列和緩存絕對(duì)是解決高并發(fā)的非常有效的辦法。比如郵件發(fā)送,這類(lèi)功能其實(shí)客戶(hù)端并不需要等待完成,所以我們?cè)谇岸酥恍枰恢卑岩l(fā)送的郵件地址,內(nèi)容等一并放到隊(duì)列里,后臺(tái)程序慢慢從隊(duì)列里面去取就OK。對(duì)于隊(duì)列的解決方案有許多,比如memcache,redis等。
關(guān)于memcache,前段時(shí)間嘗試自己用memcache來(lái)寫(xiě)了一個(gè)隊(duì)列,平臺(tái)windows。最終效果非常不理想,在循環(huán)的get或set時(shí),memcache會(huì)顯得非常緩慢,并且最終的命中率一點(diǎn)都不高。在windows平臺(tái)上的redis會(huì)由于pull的不支持造成在高并發(fā)時(shí)經(jīng)常redis server gone away的情況。在*inux平臺(tái)上,redis表現(xiàn)了非常棒的性能和穩(wěn)定性,目前公司線(xiàn)上產(chǎn)品在使用redis后,已經(jīng)非常穩(wěn)定,所以redis絕對(duì)是值得使用的神器。
4.特別注意阻塞
這是一個(gè)非常嚴(yán)重的問(wèn)題。HTTP上的阻塞,MYSQL的阻塞,阻塞的結(jié)果將是服務(wù)器不能正常響應(yīng)請(qǐng)求,CPU居高不下,并且很難發(fā)現(xiàn)問(wèn)題。這要求我們?cè)陂_(kāi)發(fā)階段,對(duì)于容易引起阻塞的地方一定要特別注意,如果某段代碼執(zhí)行的時(shí)間會(huì)非常長(zhǎng),就一定要交給子進(jìn)程來(lái)做這個(gè)事情。對(duì)于這個(gè)情況,node.js是一個(gè)非常好的解決方案,因?yàn)閚ode.js正是為非阻塞而生的。并且這幾年node.js發(fā)展迅速,各類(lèi)模塊越來(lái)越多,也越來(lái)越穩(wěn)定,框架的出現(xiàn)也大大的提升了代碼編寫(xiě)的速度,像express和eventproxy這類(lèi)的,新手可以非常快的開(kāi)發(fā)一個(gè)node.js未阻塞應(yīng)用。
5.數(shù)據(jù)庫(kù)的優(yōu)化
在高并發(fā)和大數(shù)據(jù)量的情況下,分表分庫(kù)是一定要的,并且盡量按模塊分。不要相信分區(qū),分區(qū)這貨非常容易引起表崩潰,特別是MYISAM引擎下,分區(qū)不僅會(huì)在一個(gè)文件夾下產(chǎn)生一堆的文件,還非常有可能因?yàn)榇蜷_(kāi)的文件句柄過(guò)多而出現(xiàn)各種MYSQL錯(cuò)誤。
根據(jù)情況選擇不同的引擎或數(shù)據(jù)庫(kù)軟件,MYISAM,INNODB等引擎要在不同的情況下使用,MYSIAM適用于查詢(xún)多,插入少;INNODB適用于寫(xiě)入多,查詢(xún)少和事務(wù)支持。noSQL也是非常值得嘗試的產(chǎn)品,PHP對(duì)mongdb的支持還行,操作也挺方便的。
M/S在高并發(fā)下存在延遲問(wèn)題,臨時(shí)解決方案是可以用緩存。
6.靜態(tài)資源與動(dòng)態(tài)分離
帶寬是非常珍貴和昂貴的。有條件一定要使用CDN,在速度上提升會(huì)非常明顯,同時(shí)也能保證動(dòng)態(tài)程序服務(wù)器的穩(wěn)定。
好了,以上就是近期總結(jié)的一些經(jīng)驗(yàn)。