李晟
摘要:提高服務(wù)器的處理能力,是目前計(jì)算機(jī)界的一個(gè)關(guān)鍵問題,服務(wù)器性能的好壞,直接影響著機(jī)器的成本和用戶的體驗(yàn)。該文首先介紹了服務(wù)器并發(fā)處理能力的定義和衡量方法,并詳細(xì)介紹了提高服務(wù)器并發(fā)處理能力的幾種方法。作為入門級(jí)的介紹,意在對(duì)傳統(tǒng)以及當(dāng)下前沿的技術(shù)作較全的概況總結(jié)。
關(guān)鍵詞:服務(wù)器;并發(fā);多進(jìn)程;I/O;性能優(yōu)化
中圖分類號(hào):TP368.5 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2014)28-6764-03
1 什么是服務(wù)器并發(fā)處理能力
一臺(tái)服務(wù)器在單位時(shí)間里能處理的請(qǐng)求越多,服務(wù)器的能力越高,也就是服務(wù)器并發(fā)處理能力越強(qiáng)。如何提高服務(wù)器的處理能力,是目前計(jì)算機(jī)界的一個(gè)關(guān)鍵問題[1-4]。服務(wù)器的本質(zhì)工作就是,爭(zhēng)取以最快的速度將內(nèi)核緩沖區(qū)中的用戶請(qǐng)求數(shù)據(jù)都拿出來,然后盡快處理,再將響應(yīng)數(shù)據(jù)放到一塊又能夠與發(fā)送數(shù)據(jù)的緩沖區(qū)中,接著處理下一個(gè)請(qǐng)求。
2 衡量方法
2.1 吞吐率
吞吐率:?jiǎn)挝粫r(shí)間里服務(wù)器處理的最大請(qǐng)求數(shù),單位REQ/S。
2.2 壓力測(cè)試
壓力測(cè)試前提考慮的條件:并發(fā)用戶數(shù)、總請(qǐng)求數(shù)、請(qǐng)求資源描述。
3 如何提高并發(fā)處理能力
3.1 提高CPU并發(fā)處理能力
1) 多進(jìn)程[5]
多進(jìn)程的好處不僅在于CPU時(shí)間的輪流使用,還在于對(duì)CPU計(jì)算和I/O操作進(jìn)行很好的重疊利用,這里的I/O主要指磁盤I/O和網(wǎng)絡(luò)I/O. 實(shí)際上,大多數(shù)進(jìn)程的時(shí)間主要消耗在I/O操作上,現(xiàn)代計(jì)算機(jī)的DMA技術(shù)可以讓CPU不參與I/O操作的全過程,比如進(jìn)程通過系統(tǒng)調(diào)用,使得CPU向網(wǎng)卡或者磁盤等I/O設(shè)備發(fā)出指令,然后進(jìn)程被掛起,釋放出CPU資源,等待I/O設(shè)備完成工作后通過中斷來通知進(jìn)程重新就緒。對(duì)于單任務(wù)而言,CPU大部分時(shí)間空閑,這時(shí)候多進(jìn)程的作用尤為重要。
2) 減少進(jìn)程切換
進(jìn)程擁有獨(dú)立的內(nèi)存空間,每個(gè)進(jìn)程都只能共享CPU寄存器。一個(gè)進(jìn)程被掛起的本質(zhì)是將它在CPU寄存器中的數(shù)據(jù)拿出來暫存在內(nèi)存態(tài)堆棧著那個(gè),而一個(gè)進(jìn)程恢復(fù)工作的本質(zhì)就是把它的數(shù)據(jù)重新裝入CPU寄存器,這段裝入和移出的數(shù)據(jù)稱為“硬件上下文”,除此之外,進(jìn)程上下文還包含進(jìn)程允許所需的一切狀態(tài)信息。
當(dāng)硬件上下文頻繁裝入和移出時(shí),所消耗的時(shí)間是非常明顯的。為了盡量減少上下文切換次數(shù),最簡(jiǎn)單的做法就是減少進(jìn)程數(shù),盡量使用線程并配合其它I/O模型來設(shè)計(jì)并發(fā)策略。還可考慮使用進(jìn)程綁定CPU技術(shù),增加CPU緩存的命中率。若進(jìn)程不斷在各CPU上切換,這樣舊的CPU緩存就會(huì)失效。
3) 減少使用不必要的鎖
服務(wù)器處理大量并發(fā)請(qǐng)求時(shí),多個(gè)請(qǐng)求處理任務(wù)時(shí)存在一些資源搶占競(jìng)爭(zhēng),這時(shí)一般采用“鎖”機(jī)制來控制資源的占用,當(dāng)一個(gè)任務(wù)占用資源時(shí),我們鎖住資源,這時(shí)其它任務(wù)都在等待鎖的釋放,這個(gè)現(xiàn)象稱為鎖競(jìng)爭(zhēng)。
通過鎖競(jìng)爭(zhēng)的本質(zhì),我們要意識(shí)到盡量減少并發(fā)請(qǐng)求對(duì)于共享資源的競(jìng)爭(zhēng)。比如在允許情況下關(guān)閉服務(wù)器訪問日志,這可以大大減少在鎖等待時(shí)的延遲時(shí)間。
無鎖編程[6],就是由內(nèi)核完成這個(gè)鎖機(jī)制,主要是使用原子操作替代鎖來實(shí)現(xiàn)對(duì)共享資源的訪問保護(hù) ,使用原子操作時(shí),在進(jìn)行實(shí)際的寫操作時(shí),使用了lock指令,這樣就可以阻止其他任務(wù)寫這塊內(nèi)存,避免出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)現(xiàn)象。原子操作速度比鎖快,一般要快一倍以上。例如fwrite(), fopen(),其是使用append方式寫文件,其原理就是使用了無鎖編程,無鎖編程的復(fù)雜度高,但是效率快,而且發(fā)生死鎖概率低。
4)其它
除了上述所說,要優(yōu)化服務(wù)器的并發(fā)處理能力,需關(guān)注程優(yōu)先級(jí),進(jìn)程調(diào)度器會(huì)動(dòng)態(tài)調(diào)整運(yùn)行隊(duì)列中進(jìn)程的優(yōu)先級(jí),通過top觀察進(jìn)程的PR值;關(guān)注系統(tǒng)負(fù)載,可在任何時(shí)刻查看/proc/loadavg, top中的load average也可看出;關(guān)注CPU使用率,除了用戶空間和內(nèi)核空間的CPU使用率以外,還要關(guān)注I/O wait,它是指CPU空閑并且等待I/O操作完成的時(shí)間比例。
3.2 考慮系統(tǒng)調(diào)用
進(jìn)程若運(yùn)行在用戶態(tài),這時(shí)可使用CPU和內(nèi)存來完成一些任務(wù),而當(dāng)進(jìn)程需要對(duì)硬件外設(shè)進(jìn)行操作的時(shí)候(如讀取磁盤文件,發(fā)送網(wǎng)絡(luò)數(shù)據(jù)等),就必須切換到內(nèi)核態(tài),這時(shí)它擁有更多的權(quán)力來操縱整個(gè)計(jì)算機(jī)。而系統(tǒng)調(diào)用涉及進(jìn)程從用戶態(tài)到內(nèi)核態(tài)的切換,導(dǎo)致一定的內(nèi)存交換,這也是一定程度上的上下文切換,所以系統(tǒng)調(diào)用的開銷通常認(rèn)為比較昂貴的。
3.3 考慮減少內(nèi)存分配和釋放
服務(wù)器的工作過程中,需要大量的內(nèi)存,使得內(nèi)存的分配和釋放工作尤為重要。通過改善數(shù)據(jù)結(jié)構(gòu)和算法復(fù)制度來適當(dāng)減少中間臨時(shí)變量的內(nèi)存分配及數(shù)據(jù)復(fù)制時(shí)間,而服務(wù)器本身也使用了各自的策略來提高效率。例如Apache,在運(yùn)行開始時(shí)一次申請(qǐng)大片的內(nèi)存作為內(nèi)存池,若隨后需要時(shí)就在內(nèi)存池中直接獲取,不需要再次分配,避免了頻繁的內(nèi)存分配和釋放引起的內(nèi)存整理時(shí)間。
3.4 考慮使用持久連接
持久連接也為長(zhǎng)連接,它本身是TCP通信的一種普通方式,即在一次TCP連接中持續(xù)發(fā)送多分?jǐn)?shù)據(jù)而不斷開連接,與它相反的方式稱為短連接,也就是建立連接后發(fā)送一份數(shù)據(jù)就斷開,然后再次建立連接發(fā)送下一份數(shù)據(jù), 周而復(fù)始。是否采用持久連接,完全取決于應(yīng)用特點(diǎn)。從性能角度看,建立TCP連接的操作本身是一項(xiàng)不小的開銷,在允許的情況下,連接次數(shù)越少,越有利于性能的提升; 尤其對(duì)于密集型的圖片或網(wǎng)頁等小數(shù)據(jù)請(qǐng)求處理有明顯的加速所用。
HTTP[7]長(zhǎng)連接需要瀏覽器和web服務(wù)器的共同協(xié)作,目前瀏覽器普遍支持長(zhǎng)連接,表現(xiàn)在其發(fā)出的HTTP請(qǐng)求數(shù)據(jù)頭中包含關(guān)于長(zhǎng)連接的聲明,如下: Connection: Keep-Alive。主流的web服務(wù)器都支持長(zhǎng)連接,比如apache中,可以用KeepAlive off關(guān)閉長(zhǎng)連接。
3.5 改進(jìn)I/O 模型
I/O操作根據(jù)設(shè)備的不同分為很多類型,比如內(nèi)存I/O, 網(wǎng)絡(luò)I/O, 磁盤I/O。 如何讓高速的CPU和慢速的I/O設(shè)備更好地協(xié)調(diào)工作,是現(xiàn)代計(jì)算機(jī)一直探討的話題。各種I/O模型的本質(zhì)區(qū)別在于CPU的參與方式。
1) DMA技術(shù)
I/O設(shè)備和內(nèi)存之間的數(shù)據(jù)傳輸方式由DMA控制器完成。在DMA模式下,CPU只需向DMA下達(dá)命令,讓DMA控制器來處理數(shù)據(jù)的傳送,這樣可以大大節(jié)省系統(tǒng)資源。
2)異步I/O
異步I/O指主動(dòng)請(qǐng)求數(shù)據(jù)后便可以繼續(xù)處理其它任務(wù),隨后等待I/O操作的通知,這樣進(jìn)程在數(shù)據(jù)讀寫時(shí)不發(fā)生阻塞。而同步則在數(shù)據(jù)就緒后在讀寫時(shí)必須阻塞。異步I/O是非阻塞的,當(dāng)函數(shù)返回時(shí),真正的I/O傳輸還沒開始,這讓CPU處理和I/O操作達(dá)到很好的重疊。
3)改進(jìn)多路I/O就緒通知策略[8]
epoll服務(wù)器同時(shí)處理大量的文件描述符是必不可少的,若采用同步非阻塞I/O模型,若同時(shí)接收TCP連接的數(shù)據(jù),就必須輪流對(duì)每個(gè)socket調(diào)用接收數(shù)據(jù)的方法,不管這些socket有沒有可接收的數(shù)據(jù),都要詢問一次,假如大部分socket并沒有數(shù)據(jù)可以接收,那么進(jìn)程便會(huì)浪費(fèi)很多CPU時(shí)間用于檢查這些socket.有沒有可以接收的數(shù)據(jù), 多路I/O就緒通知的出現(xiàn),提供了對(duì)大量文件描述符就緒檢查的高性能方案,它允許進(jìn)程通過一種方法同時(shí)監(jiān)視所有文件描述符,并可以快速獲得所有就緒的文件描述符,然后只針對(duì)這些文件描述符進(jìn)行數(shù)據(jù)訪問。
4)Sendfile
大多數(shù)時(shí)候,我們都向服務(wù)器請(qǐng)求靜態(tài)文件,比如圖片,樣式表等,在處理這些請(qǐng)求時(shí),磁盤文件的數(shù)據(jù)先經(jīng)過內(nèi)核緩沖區(qū),然后到用戶內(nèi)存空間,不需經(jīng)過任何處理,其又被送到網(wǎng)卡對(duì)應(yīng)的內(nèi)核緩沖區(qū),接著再被送入網(wǎng)卡進(jìn)行發(fā)送。
Linux提供sendfile()系統(tǒng)調(diào)用,可以講磁盤文件的特定部分直接傳送到代表客戶端的socket描述符,加快了靜態(tài)文件的請(qǐng)求速度,同時(shí)減少CPU和內(nèi)存的開銷。適用場(chǎng)景,對(duì)于請(qǐng)求較小的靜態(tài)文件,sendfile發(fā)揮的作用不那么明顯,因發(fā)送數(shù)據(jù)的環(huán)節(jié)在整個(gè)過程中所占時(shí)間的比例相比于大文件請(qǐng)求時(shí)小很多。
5)內(nèi)存映射
Linux內(nèi)核提供一種訪問磁盤文件的特殊方式,它可以將內(nèi)存中某塊地址空間和我們指定的磁盤文件相關(guān)聯(lián),從而對(duì)這塊內(nèi)存的訪問轉(zhuǎn)換為對(duì)磁盤文件的訪問。這種技術(shù)稱為內(nèi)存映射。
多數(shù)情況下,內(nèi)存映射可以提高磁盤I/O的性能,無須使用read()或write()等系統(tǒng)調(diào)用來訪問文件,而是通過mmap()系統(tǒng)調(diào)用來建立內(nèi)存和磁盤文件的關(guān)聯(lián),然后像訪問內(nèi)存一樣訪問文件。該機(jī)制的缺點(diǎn)是在處理較大文件時(shí),內(nèi)存映射會(huì)導(dǎo)致較大的內(nèi)存開銷,得不償失。
6)直接I/O
在linux 2.6中,內(nèi)存映射和直接訪問文件沒有本質(zhì)差異,因?yàn)閿?shù)據(jù)需要經(jīng)過2次復(fù)制,即在磁盤與內(nèi)核緩沖區(qū)之間以及在內(nèi)核緩沖區(qū)與用戶態(tài)內(nèi)存空間。
引入內(nèi)核緩沖區(qū)的目的在于提高磁盤文件的訪問性能,然而對(duì)于一些復(fù)雜的應(yīng)用,比如數(shù)據(jù)庫(kù)服務(wù)器,它們?yōu)榱诉M(jìn)一步提高性能,希望繞過內(nèi)核緩沖區(qū),由自己在用戶態(tài)空間實(shí)現(xiàn)并管理I/O緩沖區(qū),同時(shí)繞過內(nèi)核緩沖區(qū)也可以減少系統(tǒng)內(nèi)存的開銷,因內(nèi)核緩沖區(qū)本身就在使用系統(tǒng)內(nèi)存。
Linux在open()系統(tǒng)調(diào)用中增加參數(shù)選項(xiàng)O_DIRECT,即可繞過內(nèi)核緩沖區(qū)直接訪問文件,實(shí)現(xiàn)直接I/O。在Mysql中,對(duì)于Innodb存儲(chǔ)引擎[9],自身進(jìn)行數(shù)據(jù)和索引的緩存管理,可在my.cnf配置中分配raw分區(qū)跳過內(nèi)核緩沖區(qū),實(shí)現(xiàn)直接I./O。
4 改進(jìn)服務(wù)器并發(fā)策略
服務(wù)器并發(fā)策略的目的,是讓I/O操作和CPU計(jì)算盡量重疊進(jìn)行,一方面讓CPU在I/O等待時(shí)不要空閑,另一方面讓CPU在I/O調(diào)度上盡量花最少的時(shí)間。
4.1 一個(gè)進(jìn)程處理一個(gè)連接,非阻塞I/O,使用長(zhǎng)連接
Apache使用這個(gè)模型,其進(jìn)程的開銷限制了它的并發(fā)連接數(shù),但從穩(wěn)定性和兼容性的角度,則其相對(duì)安全,任何一個(gè)子進(jìn)程的崩潰不會(huì)影響Apache本身,Apache父進(jìn)程可以創(chuàng)建新的子進(jìn)程;另一方面,Apache經(jīng)過長(zhǎng)期的考驗(yàn)和廣發(fā)的使用,功能模塊非常豐富。所以對(duì)于一些并發(fā)數(shù)要求不高,還對(duì)其它功能有依賴,那么可考慮Apache這個(gè)模型。
4.2 一個(gè)進(jìn)程處理多個(gè)連接,異步I/O,使用長(zhǎng)連接
一個(gè)進(jìn)程處理多個(gè)連接,潛在條件就是多路I/O就緒通知的應(yīng)用。服務(wù)器通常維護(hù)者大量的空閑連接,有些可能由于使用長(zhǎng)連接而在等待超時(shí),有些可能是網(wǎng)絡(luò)傳輸?shù)难訒r(shí)等等,這時(shí)epoll只會(huì)關(guān)注活躍連接,而不在死連接上浪費(fèi)時(shí)間,但是select和poll會(huì)掃描所有文件描述符,這個(gè)是個(gè)非常昂貴的開銷。一個(gè)典型的應(yīng)用就是圖片服務(wù)器,它們希望為用戶提供網(wǎng)頁中大量圖片的快速下載,采用長(zhǎng)連接,但是這些大量連接在等待超時(shí)關(guān)閉前處于空閑狀態(tài),這種情況下,epoll依然能很好工作。
5 改進(jìn)硬件環(huán)境
硬件環(huán)境,服務(wù)器的硬件配置對(duì)站點(diǎn)代理的性能提升肯定是有的,但這里不作詳細(xì)討論。
6 結(jié)束語
本文針對(duì)提高服務(wù)器并發(fā)處理能力若干方法進(jìn)行了分析和總結(jié),在實(shí)際的生產(chǎn)環(huán)境中,我們可以采用這里的部分方法,優(yōu)化服務(wù)器的性能,達(dá)到最優(yōu)性能,真正做到海量服務(wù)。
參考文獻(xiàn):
[1] 孟憲福.具有并發(fā)處理能力的DOS系統(tǒng)的I/O控制策略研究[J].計(jì)算機(jī)工程與應(yīng)用,1992(5):1-3.
[2] 余靜.Windows服務(wù)器并發(fā)控制技術(shù)[J].通信技術(shù),2012(12):142-144.
[3] 汪少敏,趙猛,朱振博,王艷琦.基于多核處理器并發(fā)計(jì)算軟件構(gòu)架設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)科學(xué),2008(7):283-285.
[4] 馬曉星,呂建.分布式Web服務(wù)器技術(shù)綜述[J].計(jì)算機(jī)科學(xué),2002(1):7-12.
[5] W.Richard.Stevens, Stephen A.Rago.UNIX環(huán)境高級(jí)編程[M].2版.北京:人民郵電出版社,2006.
[6] Daniel P.Bovent,Marco Cesati.深入理解Linux內(nèi)核[M].3版.北京:中國(guó)電力出版社,2007.
[7] David Gourley, Brian Totty. HTTP權(quán)威指南[M].北京:人民郵電出版社,2012.
[8] Jon C.Snader. 高級(jí)TCP/IP編程[M].北京:中國(guó)電力出版社,2001.
[9] Baron Scbwartz,Peter Zaitsev, Vadim Tkacbenko. 高性能MySql[M].北京:電子工業(yè)出版社,2013.