精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

當(dāng)前位置:服務(wù)器行業(yè)動態(tài) → 正文

高并發(fā)環(huán)境下服務(wù)器該如何優(yōu)化

責(zé)任編輯:zsheng |來源:企業(yè)網(wǎng)D1Net  2018-09-12 15:18:41 本文摘自:博客園

什么是服務(wù)器并發(fā)處理能力

一臺服務(wù)器在單位時間里能處理的請求越多,服務(wù)器的能力越高,也就是服務(wù)器并發(fā)處理能力越強(qiáng)。

有什么方法衡量服務(wù)器并發(fā)處理能力

1. 吞吐率

吞吐率,單位時間里服務(wù)器處理的最大請求數(shù),單位req/s。

從服務(wù)器角度,實(shí)際并發(fā)用戶數(shù)可以理解為服務(wù)器當(dāng)前維護(hù)的代表不同用戶的文件描述符總數(shù),也就是并發(fā)連接數(shù)。服務(wù)器一般會限制同時服務(wù)的最多用戶數(shù),比如apache的MaxClients參數(shù)。

這里再深入一下,對于服務(wù)器來說,服務(wù)器希望支持高吞吐率,對于用戶來說,用戶只希望等待最少的時間,顯然,雙方不能滿足,所以雙方利益的平衡點(diǎn),就是我們希望的最大并發(fā)用戶數(shù)。

2. 壓力測試

有一個原理一定要先搞清楚,假如100個用戶同時向服務(wù)器分別進(jìn)行10個請求,與1個用戶向服務(wù)器連續(xù)進(jìn)行1000次請求,對服務(wù)器的壓力是一樣嗎?實(shí)際上是不一樣的,因?qū)γ恳粋€用戶,連續(xù)發(fā)送請求實(shí)際上是指發(fā)送一個請求并接收到響應(yīng)數(shù)據(jù)后再發(fā)送下一個請求。這樣對于1個用戶向服務(wù)器連續(xù)進(jìn)行1000次請求, 任何時刻服務(wù)器的網(wǎng)卡接收緩沖區(qū)中只有1個請求,而對于100個用戶同時向服務(wù)器分別進(jìn)行10個請求,服務(wù)器的網(wǎng)卡接收緩沖區(qū)最多有100個等待處理的請求,顯然這時的服務(wù)器壓力更大。

壓力測試前提考慮的條件

并發(fā)用戶:指在某一時刻同時向服務(wù)器發(fā)送請求的用戶總數(shù)(HttpWatch)

總請求數(shù)

請求資源描述

請求等待時間(用戶等待時間)

用戶平均請求的等待時間

服務(wù)器平均請求處理的時間

硬件環(huán)境

壓力測試中關(guān)心的時間又細(xì)分以下2種:

用戶平均請求等待時間(這里暫不把數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸時間,還有用戶本地PC的計(jì)算時間計(jì)算入內(nèi))

服務(wù)器平均請求處理時間

用戶平均請求等待時間主要用于衡量服務(wù)器在一定并發(fā)用戶數(shù)下,單個用戶的服務(wù)質(zhì)量;而服務(wù)器平均請求處理時間就是吞吐率的倒數(shù),一般來說,用戶平均請求等待時間 = 服務(wù)器平均請求處理時間 * 并發(fā)用戶數(shù)

怎么提高服務(wù)器的并發(fā)處理能力

1. 提高CPU并發(fā)計(jì)算能力

服務(wù)器之所以可以同時處理多個請求,在于操作系統(tǒng)通過多執(zhí)行流體系設(shè)計(jì)使得多個任務(wù)可以輪流使用系統(tǒng)資源,這些資源包括CPU,內(nèi)存以及I/O。這里的I/O主要指磁盤I/O和網(wǎng)絡(luò)I/O。

多進(jìn)程 & 多線程

多執(zhí)行流的一般實(shí)現(xiàn)便是進(jìn)程,多進(jìn)程的好處可以對CPU時間的輪流使用,對CPU計(jì)算和IO操作重疊利用。這里的IO主要是指磁盤IO和網(wǎng)絡(luò)IO,相對CPU而言,它們慢的可憐。

而實(shí)際上,大多數(shù)進(jìn)程的時間主要消耗在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)程重新就緒。對于單任務(wù)而言,CPU大部分時間空閑,這時候多進(jìn)程的作用尤為重要。

多進(jìn)程不僅能夠提高CPU的并發(fā)度。其優(yōu)越性還體現(xiàn)在獨(dú)立的內(nèi)存地址空間和生命周期所帶來的穩(wěn)定性和健壯性,其中一個進(jìn)程崩潰不會影響到另一個進(jìn)程。

但是進(jìn)程也有如下缺點(diǎn):

fork()系統(tǒng)調(diào)用開銷很大:prefork

進(jìn)程間調(diào)度和上下文切換成本:減少進(jìn)程數(shù)量

龐大的內(nèi)存重復(fù):共享內(nèi)存

IPC編程相對比較麻煩

減少進(jìn)程切換

當(dāng)硬件上下文頻繁裝入和移出時,所消耗的時間是非常可觀的。可用Nmon工具監(jiān)視服務(wù)器每秒的上下文切換次數(shù)。為了盡量減少上下文切換次數(shù),最簡單的做法就是減少進(jìn)程數(shù),盡量使用線程并配合其它I/O模型來設(shè)計(jì)并發(fā)策略。

還可以考慮使用進(jìn)程綁定CPU技術(shù),增加CPU緩存的命中率。若進(jìn)程不斷在各CPU上切換,這樣舊的CPU緩存就會失效。

減少使用不必要的鎖

服務(wù)器處理大量并發(fā)請求時,多個請求處理任務(wù)時存在一些資源搶占競爭,這時一般采用“鎖”機(jī)制來控制資源的占用,當(dāng)一個任務(wù)占用資源時,我們鎖住資源,這時其它任務(wù)都在等待鎖的釋放,這個現(xiàn)象稱為鎖競爭。

通過鎖競爭的本質(zhì),我們要意識到盡量減少并發(fā)請求對于共享資源的競爭。比如在允許情況下關(guān)閉服務(wù)器訪問日志,這可以大大減少在鎖等待時的延遲時間。要最大程度減少無辜的等待時間。

這里說下無鎖編程,就是由內(nèi)核完成這個鎖機(jī)制,主要是使用原子操作替代鎖來實(shí)現(xiàn)對共享資源的訪問保護(hù),使用原子操作時,在進(jìn)行實(shí)際的寫操作時,使用了lock指令,這樣就可以阻止其他任務(wù)寫這塊內(nèi)存,避免出現(xiàn)數(shù)據(jù)競爭現(xiàn)象。原子操作速度比鎖快,一般要快一倍以上。

例如fwrite(), fopen(),其是使用append方式寫文件,其原理就是使用了無鎖編程,無鎖編程的復(fù)雜度高,但是效率快,而且發(fā)生死鎖概率低。

考慮進(jìn)程優(yōu)先級

進(jìn)程調(diào)度器會動態(tài)調(diào)整運(yùn)行隊(duì)列中進(jìn)程的優(yōu)先級,通過top觀察進(jìn)程的PR值。

考慮系統(tǒng)負(fù)載

可在任何時刻查看/proc/loadavg,top中的load average也可看出。

考慮CPU使用率

除了用戶空間和內(nèi)核空間的CPU使用率以外,還要關(guān)注I/O wait,它是指CPU空閑并且等待I/O操作完成的時間比例(top中查看wa的值)。

2. 考慮減少內(nèi)存分配和釋放

服務(wù)器的工作過程中,需要大量的內(nèi)存,使得內(nèi)存的分配和釋放工作尤為重要。可以通過改善數(shù)據(jù)結(jié)構(gòu)和算法復(fù)制度來適當(dāng)減少中間臨時變量的內(nèi)存分配及數(shù)據(jù)復(fù)制時間,而服務(wù)器本身也使用了各自的策略來提高效率。

例如Apache,在運(yùn)行開始時一次申請大片的內(nèi)存作為內(nèi)存池,若隨后需要時就在內(nèi)存池中直接獲取,不需要再次分配,避免了頻繁的內(nèi)存分配和釋放引起的內(nèi)存整理時間。

再如Nginx使用多線程來處理請求,使得多個線程之間可以共享內(nèi)存資源,從而令它的內(nèi)存總體使用量大大減少,另外,nginx分階段的內(nèi)存分配策略,按需分配,及時釋放,使得內(nèi)存使用量保持在很小的數(shù)量范圍。

另外,還可以考慮共享內(nèi)存。共享內(nèi)存指在多處理器的計(jì)算機(jī)系統(tǒng)中,可以被不同中央處理器(CPU)訪問的大容量內(nèi)存,也可以由不同進(jìn)程共享,是非常快的進(jìn)程通信方式。

但是使用共享內(nèi)存也有不好的地方,就是對于多機(jī)器時數(shù)據(jù)不好統(tǒng)一。

shell命令ipcs可用來顯示系統(tǒng)下共享內(nèi)存的狀態(tài),函數(shù)shmget可以創(chuàng)建或打開一塊共享內(nèi)存區(qū),函數(shù)shmat將一個存在的共享內(nèi)存段連接到本進(jìn)程空間,函數(shù)shmctl可以對共享內(nèi)存段進(jìn)行多種操作,函數(shù)shmdt函數(shù)分離該共享內(nèi)存。

3. 考慮使用持久連接

持久連接也稱為長連接,它本身是TCP通信的一種普通方式,即在一次TCP連接中持續(xù)發(fā)送多分?jǐn)?shù)據(jù)而不斷開連接,與它相反的方式稱為短連接,也就是建立連接后發(fā)送一份數(shù)據(jù)就斷開,然后再次建立連接發(fā)送下一份數(shù)據(jù), 周而復(fù)始。是否采用持久連接,完全取決于應(yīng)用特點(diǎn)。

從性能角度看,建立TCP連接的操作本身是一項(xiàng)不小的開銷,在允許的情況下,連接次數(shù)越少,越有利于性能的提升; 尤其對于密集型的圖片或網(wǎng)頁等小數(shù)據(jù)請求處理有明顯的加速所用。

HTTP長連接需要瀏覽器和web服務(wù)器的共同協(xié)作,目前瀏覽器普遍支持長連接,表現(xiàn)在其發(fā)出的HTTP請求數(shù)據(jù)頭中包含關(guān)于長連接的聲明,如下: Connection: Keep-Alive,主流的web服務(wù)器都支持長連接,比如apache中,可以用KeepAlive off關(guān)閉長連接。

對于長連接的有效使用,還有關(guān)鍵一點(diǎn)在于長連接超時時間的設(shè)置,即長連接在什么時候關(guān)閉嗎? Apache的默認(rèn)設(shè)置為5s, 若這個時間設(shè)置過長,則可能導(dǎo)致資源無效占有,維持大量空閑進(jìn)程,影響服務(wù)器性能。

4. 改進(jìn)I/O 模型

I/O操作根據(jù)設(shè)備的不同分為很多類型,比如內(nèi)存I/O, 網(wǎng)絡(luò)I/O, 磁盤I/O。對于網(wǎng)絡(luò)I/O和磁盤I/O, 它們的速度要慢很多,盡管使用RAID磁盤陣列可通過并行磁盤磁盤來加快磁盤I/O速度,購買大連獨(dú)享網(wǎng)絡(luò)帶寬以及使用高帶寬網(wǎng)絡(luò)適配器可以提高網(wǎng)絡(luò)i/O的速度。

但這些I/O操作需要內(nèi)核系統(tǒng)調(diào)用來完成,這些需要CPU來調(diào)度,這使得CPU不得不浪費(fèi)寶貴的時間來等待慢速I/O操作。我們希望讓CPU足夠少的時間在I/O操作的調(dià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指主動請求數(shù)據(jù)后便可以繼續(xù)處理其它任務(wù),隨后等待I/O操作的通知,這樣進(jìn)程在數(shù)據(jù)讀寫時不發(fā)生阻塞。

異步I/O是非阻塞的,當(dāng)函數(shù)返回時,真正的I/O傳輸已經(jīng)完成,這讓CPU處理和I/O操作達(dá)到很好的重疊。

3. I/O多路復(fù)用

服務(wù)器同時處理大量的文件描述符是必不可少的,若采用同步非阻塞I/O模型,若同時接收TCP連接的數(shù)據(jù),就必須輪流對每個socket調(diào)用接收數(shù)據(jù)的方法,不管這些socket有沒有可接收的數(shù)據(jù),都要詢問一次。

假如大部分socket并沒有數(shù)據(jù)可以接收,那么進(jìn)程便會浪費(fèi)很多CPU時間用于檢查這些socket有沒有可以接收的數(shù)據(jù)。多路I/O就緒通知的出現(xiàn),提供了對大量文件描述符就緒檢查的高性能方案,它允許進(jìn)程通過一種方法同時監(jiān)視所有文件描述符,并可以快速獲得所有就緒的文件描述符,然后只針對這些文件描述符進(jìn)行數(shù)據(jù)訪問。

epoll可以同時支持水平觸發(fā)和邊緣觸發(fā),理論上邊緣觸發(fā)性能更高,但是代碼實(shí)現(xiàn)復(fù)雜,因?yàn)槿魏我馔獾膩G失事件都會造成請求處理錯誤。

epoll主要有2大改進(jìn):

epoll只告知就緒的文件描述符,而且當(dāng)調(diào)用epoll_wait()獲得文件描述符時,返回并不是實(shí)際的描述符,而是一個代表就緒描述符數(shù)量的值,然后只需去epoll指定的一個數(shù)組中依次取得相應(yīng)數(shù)量的文件描述符即可,這里使用了內(nèi)存映射(mmap)技術(shù),這樣徹底省掉了這些文件描述符在系統(tǒng)調(diào)用時復(fù)制的開銷。

epoll采用基于事件的就緒通知方式。其事先通過epoll_ctrl()注冊每一個文件描述符,一旦某個文件描述符就緒時,內(nèi)核會采用類似callback的回調(diào)機(jī)制,當(dāng)進(jìn)程調(diào)用epoll_wait()時得到通知。

4. Sendfile

大多數(shù)時候,我們都向服務(wù)器請求靜態(tài)文件,比如圖片,樣式表等,在處理這些請求時,磁盤文件的數(shù)據(jù)先經(jīng)過內(nèi)核緩沖區(qū),然后到用戶內(nèi)存空間,不需經(jīng)過任何處理,其又被送到網(wǎng)卡對應(yīng)的內(nèi)核緩沖區(qū),接著再被送入網(wǎng)卡進(jìn)行發(fā)送。

Linux提供sendfile()系統(tǒng)調(diào)用,可以講磁盤文件的特定部分直接傳送到代表客戶端的socket描述符,加快了靜態(tài)文件的請求速度,同時減少CPU和內(nèi)存的開銷。

適用場景: 對于請求較小的靜態(tài)文件,sendfile發(fā)揮的作用不那么明顯,因發(fā)送數(shù)據(jù)的環(huán)節(jié)在整個過程中所占時間的比例相比于大文件請求時小很多。

5. 內(nèi)存映射

Linux內(nèi)核提供一種訪問磁盤文件的特殊方式,它可以將內(nèi)存中某塊地址空間和我們指定的磁盤文件相關(guān)聯(lián),從而對這塊內(nèi)存的訪問轉(zhuǎn)換為對磁盤文件的訪問。這種技術(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)存一樣自由訪問文件。

缺點(diǎn):在處理較大文件時,內(nèi)存映射會導(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ū)的目的在于提高磁盤文件的訪問性能,然而對于一些復(fù)雜的應(yīng)用,比如數(shù)據(jù)庫服務(wù)器,它們?yōu)榱诉M(jìn)一步提高性能,希望繞過內(nèi)核緩沖區(qū),由自己在用戶態(tài)空間實(shí)現(xiàn)并管理I/O緩沖區(qū),比如數(shù)據(jù)庫可根據(jù)更加合理的策略來提高查詢緩存命中率。另一方面,繞過內(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中,對于Innodb存儲引擎,自身進(jìn)行數(shù)據(jù)和索引的緩存管理,可在my.cnf配置中分配raw分區(qū)跳過內(nèi)核緩沖區(qū),實(shí)現(xiàn)直接I/O。

改進(jìn)服務(wù)器并發(fā)策略

服務(wù)器并發(fā)策略的目的,是讓I/O操作和CPU計(jì)算盡量重疊進(jìn)行,一方面讓CPU在I/O等待時不要空閑,另一方面讓CPU在I/O調(diào)度上盡量花最少的時間。

一個進(jìn)程處理一個連接,非阻塞I/O

這樣會存在多個并發(fā)請求同時到達(dá)時,服務(wù)器必然要準(zhǔn)備多個進(jìn)程來處理請求。其進(jìn)程的開銷限制了它的并發(fā)連接數(shù)。但從穩(wěn)定性和兼容性的角度,則其相對安全,任何一個子進(jìn)程的崩潰不會影響服務(wù)器本身,父進(jìn)程可以創(chuàng)建新的子進(jìn)程;這種策略典型的例子就是Apache的fork和prefork模式。對于并發(fā)數(shù)不高(如150以內(nèi))的站點(diǎn)同時依賴Apache其它功能時的應(yīng)用選擇Apache還是可以的。

一個線程處理一個連接,非阻塞IO

這種方式允許在一個進(jìn)程中通過多個線程來處理多個連接,一個線程處理一個連接。Apache的worker模式就是這種典型例子,使其可支持更多的并發(fā)連接。不過這種模式的總體性能還不如prefork,所以一般不選用worker模式。

一個進(jìn)程處理多個連接,異步I/O

一個線程同時處理多個連接,潛在的前提條件就是使用IO多路復(fù)用就緒通知。這種情況下,將處理多個連接的進(jìn)程叫做worker進(jìn)程或服務(wù)進(jìn)程。worker的數(shù)量可以配置,如Nginx中的worker_processes 4。

一個線程處理多個連接,異步IO

即使有高性能的IO多路復(fù)用就緒通知,但磁盤IO的等待還是無法避免的。更加高效的方法是對磁盤文件使用異步IO,目前很少有Web服務(wù)器真正意義上支持這種異步IO。

6. 改進(jìn)硬件環(huán)境

還有一點(diǎn)要提及的是硬件環(huán)境,服務(wù)器的硬件配置對應(yīng)用程序的性能提升往往是最直接,也是最簡單的方式,這就是所謂的scale up。這里不做論述。

關(guān)鍵字:優(yōu)化服務(wù)器環(huán)境

本文摘自:博客園

x 高并發(fā)環(huán)境下服務(wù)器該如何優(yōu)化 掃一掃
分享本文到朋友圈
當(dāng)前位置:服務(wù)器行業(yè)動態(tài) → 正文

高并發(fā)環(huán)境下服務(wù)器該如何優(yōu)化

責(zé)任編輯:zsheng |來源:企業(yè)網(wǎng)D1Net  2018-09-12 15:18:41 本文摘自:博客園

什么是服務(wù)器并發(fā)處理能力

一臺服務(wù)器在單位時間里能處理的請求越多,服務(wù)器的能力越高,也就是服務(wù)器并發(fā)處理能力越強(qiáng)。

有什么方法衡量服務(wù)器并發(fā)處理能力

1. 吞吐率

吞吐率,單位時間里服務(wù)器處理的最大請求數(shù),單位req/s。

從服務(wù)器角度,實(shí)際并發(fā)用戶數(shù)可以理解為服務(wù)器當(dāng)前維護(hù)的代表不同用戶的文件描述符總數(shù),也就是并發(fā)連接數(shù)。服務(wù)器一般會限制同時服務(wù)的最多用戶數(shù),比如apache的MaxClients參數(shù)。

這里再深入一下,對于服務(wù)器來說,服務(wù)器希望支持高吞吐率,對于用戶來說,用戶只希望等待最少的時間,顯然,雙方不能滿足,所以雙方利益的平衡點(diǎn),就是我們希望的最大并發(fā)用戶數(shù)。

2. 壓力測試

有一個原理一定要先搞清楚,假如100個用戶同時向服務(wù)器分別進(jìn)行10個請求,與1個用戶向服務(wù)器連續(xù)進(jìn)行1000次請求,對服務(wù)器的壓力是一樣嗎?實(shí)際上是不一樣的,因?qū)γ恳粋€用戶,連續(xù)發(fā)送請求實(shí)際上是指發(fā)送一個請求并接收到響應(yīng)數(shù)據(jù)后再發(fā)送下一個請求。這樣對于1個用戶向服務(wù)器連續(xù)進(jìn)行1000次請求, 任何時刻服務(wù)器的網(wǎng)卡接收緩沖區(qū)中只有1個請求,而對于100個用戶同時向服務(wù)器分別進(jìn)行10個請求,服務(wù)器的網(wǎng)卡接收緩沖區(qū)最多有100個等待處理的請求,顯然這時的服務(wù)器壓力更大。

壓力測試前提考慮的條件

并發(fā)用戶:指在某一時刻同時向服務(wù)器發(fā)送請求的用戶總數(shù)(HttpWatch)

總請求數(shù)

請求資源描述

請求等待時間(用戶等待時間)

用戶平均請求的等待時間

服務(wù)器平均請求處理的時間

硬件環(huán)境

壓力測試中關(guān)心的時間又細(xì)分以下2種:

用戶平均請求等待時間(這里暫不把數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸時間,還有用戶本地PC的計(jì)算時間計(jì)算入內(nèi))

服務(wù)器平均請求處理時間

用戶平均請求等待時間主要用于衡量服務(wù)器在一定并發(fā)用戶數(shù)下,單個用戶的服務(wù)質(zhì)量;而服務(wù)器平均請求處理時間就是吞吐率的倒數(shù),一般來說,用戶平均請求等待時間 = 服務(wù)器平均請求處理時間 * 并發(fā)用戶數(shù)

怎么提高服務(wù)器的并發(fā)處理能力

1. 提高CPU并發(fā)計(jì)算能力

服務(wù)器之所以可以同時處理多個請求,在于操作系統(tǒng)通過多執(zhí)行流體系設(shè)計(jì)使得多個任務(wù)可以輪流使用系統(tǒng)資源,這些資源包括CPU,內(nèi)存以及I/O。這里的I/O主要指磁盤I/O和網(wǎng)絡(luò)I/O。

多進(jìn)程 & 多線程

多執(zhí)行流的一般實(shí)現(xiàn)便是進(jìn)程,多進(jìn)程的好處可以對CPU時間的輪流使用,對CPU計(jì)算和IO操作重疊利用。這里的IO主要是指磁盤IO和網(wǎng)絡(luò)IO,相對CPU而言,它們慢的可憐。

而實(shí)際上,大多數(shù)進(jìn)程的時間主要消耗在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)程重新就緒。對于單任務(wù)而言,CPU大部分時間空閑,這時候多進(jìn)程的作用尤為重要。

多進(jìn)程不僅能夠提高CPU的并發(fā)度。其優(yōu)越性還體現(xiàn)在獨(dú)立的內(nèi)存地址空間和生命周期所帶來的穩(wěn)定性和健壯性,其中一個進(jìn)程崩潰不會影響到另一個進(jìn)程。

但是進(jìn)程也有如下缺點(diǎn):

fork()系統(tǒng)調(diào)用開銷很大:prefork

進(jìn)程間調(diào)度和上下文切換成本:減少進(jìn)程數(shù)量

龐大的內(nèi)存重復(fù):共享內(nèi)存

IPC編程相對比較麻煩

減少進(jìn)程切換

當(dāng)硬件上下文頻繁裝入和移出時,所消耗的時間是非常可觀的。可用Nmon工具監(jiān)視服務(wù)器每秒的上下文切換次數(shù)。為了盡量減少上下文切換次數(shù),最簡單的做法就是減少進(jìn)程數(shù),盡量使用線程并配合其它I/O模型來設(shè)計(jì)并發(fā)策略。

還可以考慮使用進(jìn)程綁定CPU技術(shù),增加CPU緩存的命中率。若進(jìn)程不斷在各CPU上切換,這樣舊的CPU緩存就會失效。

減少使用不必要的鎖

服務(wù)器處理大量并發(fā)請求時,多個請求處理任務(wù)時存在一些資源搶占競爭,這時一般采用“鎖”機(jī)制來控制資源的占用,當(dāng)一個任務(wù)占用資源時,我們鎖住資源,這時其它任務(wù)都在等待鎖的釋放,這個現(xiàn)象稱為鎖競爭。

通過鎖競爭的本質(zhì),我們要意識到盡量減少并發(fā)請求對于共享資源的競爭。比如在允許情況下關(guān)閉服務(wù)器訪問日志,這可以大大減少在鎖等待時的延遲時間。要最大程度減少無辜的等待時間。

這里說下無鎖編程,就是由內(nèi)核完成這個鎖機(jī)制,主要是使用原子操作替代鎖來實(shí)現(xiàn)對共享資源的訪問保護(hù),使用原子操作時,在進(jìn)行實(shí)際的寫操作時,使用了lock指令,這樣就可以阻止其他任務(wù)寫這塊內(nèi)存,避免出現(xiàn)數(shù)據(jù)競爭現(xiàn)象。原子操作速度比鎖快,一般要快一倍以上。

例如fwrite(), fopen(),其是使用append方式寫文件,其原理就是使用了無鎖編程,無鎖編程的復(fù)雜度高,但是效率快,而且發(fā)生死鎖概率低。

考慮進(jìn)程優(yōu)先級

進(jìn)程調(diào)度器會動態(tài)調(diào)整運(yùn)行隊(duì)列中進(jìn)程的優(yōu)先級,通過top觀察進(jìn)程的PR值。

考慮系統(tǒng)負(fù)載

可在任何時刻查看/proc/loadavg,top中的load average也可看出。

考慮CPU使用率

除了用戶空間和內(nèi)核空間的CPU使用率以外,還要關(guān)注I/O wait,它是指CPU空閑并且等待I/O操作完成的時間比例(top中查看wa的值)。

2. 考慮減少內(nèi)存分配和釋放

服務(wù)器的工作過程中,需要大量的內(nèi)存,使得內(nèi)存的分配和釋放工作尤為重要。可以通過改善數(shù)據(jù)結(jié)構(gòu)和算法復(fù)制度來適當(dāng)減少中間臨時變量的內(nèi)存分配及數(shù)據(jù)復(fù)制時間,而服務(wù)器本身也使用了各自的策略來提高效率。

例如Apache,在運(yùn)行開始時一次申請大片的內(nèi)存作為內(nèi)存池,若隨后需要時就在內(nèi)存池中直接獲取,不需要再次分配,避免了頻繁的內(nèi)存分配和釋放引起的內(nèi)存整理時間。

再如Nginx使用多線程來處理請求,使得多個線程之間可以共享內(nèi)存資源,從而令它的內(nèi)存總體使用量大大減少,另外,nginx分階段的內(nèi)存分配策略,按需分配,及時釋放,使得內(nèi)存使用量保持在很小的數(shù)量范圍。

另外,還可以考慮共享內(nèi)存。共享內(nèi)存指在多處理器的計(jì)算機(jī)系統(tǒng)中,可以被不同中央處理器(CPU)訪問的大容量內(nèi)存,也可以由不同進(jìn)程共享,是非常快的進(jìn)程通信方式。

但是使用共享內(nèi)存也有不好的地方,就是對于多機(jī)器時數(shù)據(jù)不好統(tǒng)一。

shell命令ipcs可用來顯示系統(tǒng)下共享內(nèi)存的狀態(tài),函數(shù)shmget可以創(chuàng)建或打開一塊共享內(nèi)存區(qū),函數(shù)shmat將一個存在的共享內(nèi)存段連接到本進(jìn)程空間,函數(shù)shmctl可以對共享內(nèi)存段進(jìn)行多種操作,函數(shù)shmdt函數(shù)分離該共享內(nèi)存。

3. 考慮使用持久連接

持久連接也稱為長連接,它本身是TCP通信的一種普通方式,即在一次TCP連接中持續(xù)發(fā)送多分?jǐn)?shù)據(jù)而不斷開連接,與它相反的方式稱為短連接,也就是建立連接后發(fā)送一份數(shù)據(jù)就斷開,然后再次建立連接發(fā)送下一份數(shù)據(jù), 周而復(fù)始。是否采用持久連接,完全取決于應(yīng)用特點(diǎn)。

從性能角度看,建立TCP連接的操作本身是一項(xiàng)不小的開銷,在允許的情況下,連接次數(shù)越少,越有利于性能的提升; 尤其對于密集型的圖片或網(wǎng)頁等小數(shù)據(jù)請求處理有明顯的加速所用。

HTTP長連接需要瀏覽器和web服務(wù)器的共同協(xié)作,目前瀏覽器普遍支持長連接,表現(xiàn)在其發(fā)出的HTTP請求數(shù)據(jù)頭中包含關(guān)于長連接的聲明,如下: Connection: Keep-Alive,主流的web服務(wù)器都支持長連接,比如apache中,可以用KeepAlive off關(guān)閉長連接。

對于長連接的有效使用,還有關(guān)鍵一點(diǎn)在于長連接超時時間的設(shè)置,即長連接在什么時候關(guān)閉嗎? Apache的默認(rèn)設(shè)置為5s, 若這個時間設(shè)置過長,則可能導(dǎo)致資源無效占有,維持大量空閑進(jìn)程,影響服務(wù)器性能。

4. 改進(jìn)I/O 模型

I/O操作根據(jù)設(shè)備的不同分為很多類型,比如內(nèi)存I/O, 網(wǎng)絡(luò)I/O, 磁盤I/O。對于網(wǎng)絡(luò)I/O和磁盤I/O, 它們的速度要慢很多,盡管使用RAID磁盤陣列可通過并行磁盤磁盤來加快磁盤I/O速度,購買大連獨(dú)享網(wǎng)絡(luò)帶寬以及使用高帶寬網(wǎng)絡(luò)適配器可以提高網(wǎng)絡(luò)i/O的速度。

但這些I/O操作需要內(nèi)核系統(tǒng)調(diào)用來完成,這些需要CPU來調(diào)度,這使得CPU不得不浪費(fèi)寶貴的時間來等待慢速I/O操作。我們希望讓CPU足夠少的時間在I/O操作的調(dià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指主動請求數(shù)據(jù)后便可以繼續(xù)處理其它任務(wù),隨后等待I/O操作的通知,這樣進(jìn)程在數(shù)據(jù)讀寫時不發(fā)生阻塞。

異步I/O是非阻塞的,當(dāng)函數(shù)返回時,真正的I/O傳輸已經(jīng)完成,這讓CPU處理和I/O操作達(dá)到很好的重疊。

3. I/O多路復(fù)用

服務(wù)器同時處理大量的文件描述符是必不可少的,若采用同步非阻塞I/O模型,若同時接收TCP連接的數(shù)據(jù),就必須輪流對每個socket調(diào)用接收數(shù)據(jù)的方法,不管這些socket有沒有可接收的數(shù)據(jù),都要詢問一次。

假如大部分socket并沒有數(shù)據(jù)可以接收,那么進(jìn)程便會浪費(fèi)很多CPU時間用于檢查這些socket有沒有可以接收的數(shù)據(jù)。多路I/O就緒通知的出現(xiàn),提供了對大量文件描述符就緒檢查的高性能方案,它允許進(jìn)程通過一種方法同時監(jiān)視所有文件描述符,并可以快速獲得所有就緒的文件描述符,然后只針對這些文件描述符進(jìn)行數(shù)據(jù)訪問。

epoll可以同時支持水平觸發(fā)和邊緣觸發(fā),理論上邊緣觸發(fā)性能更高,但是代碼實(shí)現(xiàn)復(fù)雜,因?yàn)槿魏我馔獾膩G失事件都會造成請求處理錯誤。

epoll主要有2大改進(jìn):

epoll只告知就緒的文件描述符,而且當(dāng)調(diào)用epoll_wait()獲得文件描述符時,返回并不是實(shí)際的描述符,而是一個代表就緒描述符數(shù)量的值,然后只需去epoll指定的一個數(shù)組中依次取得相應(yīng)數(shù)量的文件描述符即可,這里使用了內(nèi)存映射(mmap)技術(shù),這樣徹底省掉了這些文件描述符在系統(tǒng)調(diào)用時復(fù)制的開銷。

epoll采用基于事件的就緒通知方式。其事先通過epoll_ctrl()注冊每一個文件描述符,一旦某個文件描述符就緒時,內(nèi)核會采用類似callback的回調(diào)機(jī)制,當(dāng)進(jìn)程調(diào)用epoll_wait()時得到通知。

4. Sendfile

大多數(shù)時候,我們都向服務(wù)器請求靜態(tài)文件,比如圖片,樣式表等,在處理這些請求時,磁盤文件的數(shù)據(jù)先經(jīng)過內(nèi)核緩沖區(qū),然后到用戶內(nèi)存空間,不需經(jīng)過任何處理,其又被送到網(wǎng)卡對應(yīng)的內(nèi)核緩沖區(qū),接著再被送入網(wǎng)卡進(jìn)行發(fā)送。

Linux提供sendfile()系統(tǒng)調(diào)用,可以講磁盤文件的特定部分直接傳送到代表客戶端的socket描述符,加快了靜態(tài)文件的請求速度,同時減少CPU和內(nèi)存的開銷。

適用場景: 對于請求較小的靜態(tài)文件,sendfile發(fā)揮的作用不那么明顯,因發(fā)送數(shù)據(jù)的環(huán)節(jié)在整個過程中所占時間的比例相比于大文件請求時小很多。

5. 內(nèi)存映射

Linux內(nèi)核提供一種訪問磁盤文件的特殊方式,它可以將內(nèi)存中某塊地址空間和我們指定的磁盤文件相關(guān)聯(lián),從而對這塊內(nèi)存的訪問轉(zhuǎn)換為對磁盤文件的訪問。這種技術(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)存一樣自由訪問文件。

缺點(diǎn):在處理較大文件時,內(nèi)存映射會導(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ū)的目的在于提高磁盤文件的訪問性能,然而對于一些復(fù)雜的應(yīng)用,比如數(shù)據(jù)庫服務(wù)器,它們?yōu)榱诉M(jìn)一步提高性能,希望繞過內(nèi)核緩沖區(qū),由自己在用戶態(tài)空間實(shí)現(xiàn)并管理I/O緩沖區(qū),比如數(shù)據(jù)庫可根據(jù)更加合理的策略來提高查詢緩存命中率。另一方面,繞過內(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中,對于Innodb存儲引擎,自身進(jìn)行數(shù)據(jù)和索引的緩存管理,可在my.cnf配置中分配raw分區(qū)跳過內(nèi)核緩沖區(qū),實(shí)現(xiàn)直接I/O。

改進(jìn)服務(wù)器并發(fā)策略

服務(wù)器并發(fā)策略的目的,是讓I/O操作和CPU計(jì)算盡量重疊進(jìn)行,一方面讓CPU在I/O等待時不要空閑,另一方面讓CPU在I/O調(diào)度上盡量花最少的時間。

一個進(jìn)程處理一個連接,非阻塞I/O

這樣會存在多個并發(fā)請求同時到達(dá)時,服務(wù)器必然要準(zhǔn)備多個進(jìn)程來處理請求。其進(jìn)程的開銷限制了它的并發(fā)連接數(shù)。但從穩(wěn)定性和兼容性的角度,則其相對安全,任何一個子進(jìn)程的崩潰不會影響服務(wù)器本身,父進(jìn)程可以創(chuàng)建新的子進(jìn)程;這種策略典型的例子就是Apache的fork和prefork模式。對于并發(fā)數(shù)不高(如150以內(nèi))的站點(diǎn)同時依賴Apache其它功能時的應(yīng)用選擇Apache還是可以的。

一個線程處理一個連接,非阻塞IO

這種方式允許在一個進(jìn)程中通過多個線程來處理多個連接,一個線程處理一個連接。Apache的worker模式就是這種典型例子,使其可支持更多的并發(fā)連接。不過這種模式的總體性能還不如prefork,所以一般不選用worker模式。

一個進(jìn)程處理多個連接,異步I/O

一個線程同時處理多個連接,潛在的前提條件就是使用IO多路復(fù)用就緒通知。這種情況下,將處理多個連接的進(jìn)程叫做worker進(jìn)程或服務(wù)進(jìn)程。worker的數(shù)量可以配置,如Nginx中的worker_processes 4。

一個線程處理多個連接,異步IO

即使有高性能的IO多路復(fù)用就緒通知,但磁盤IO的等待還是無法避免的。更加高效的方法是對磁盤文件使用異步IO,目前很少有Web服務(wù)器真正意義上支持這種異步IO。

6. 改進(jìn)硬件環(huán)境

還有一點(diǎn)要提及的是硬件環(huán)境,服務(wù)器的硬件配置對應(yīng)用程序的性能提升往往是最直接,也是最簡單的方式,這就是所謂的scale up。這里不做論述。

關(guān)鍵字:優(yōu)化服務(wù)器環(huán)境

本文摘自:博客園

電子周刊
回到頂部

關(guān)于我們聯(lián)系我們版權(quán)聲明隱私條款廣告服務(wù)友情鏈接投稿中心招賢納士

企業(yè)網(wǎng)版權(quán)所有 ©2010-2024 京ICP備09108050號-6 京公網(wǎng)安備 11010502049343號

^
  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 济阳县| 义乌市| 婺源县| 沁源县| 明星| 南汇区| 石狮市| 台州市| 土默特右旗| 柯坪县| 廊坊市| 融水| 三原县| 宜宾县| 辉南县| 五指山市| 玉环县| 蒲江县| 渭源县| 镇江市| 绥宁县| 喜德县| 同德县| 玉屏| 长白| 中西区| 友谊县| 临海市| 长泰县| 周宁县| 樟树市| 诸暨市| 乳源| 乃东县| 德阳市| 绥中县| 秭归县| 蓝山县| 简阳市| 八宿县| 安宁市|