Apache 性能調(diào)優(yōu)

2021-10-13 18:21 更新

Apache 2.x是一個(gè)通用的Web服務(wù)器,旨在提供靈活性,可移植性和性能之間的平衡。雖然它沒(méi)有專(zhuān)門(mén)設(shè)計(jì)用于設(shè)置基準(zhǔn)記錄,但Apache 2.x在許多實(shí)際情況下都具有高性能。

與Apache 1.3相比,版本2.x包含許多額外的優(yōu)化,以提高吞吐量和可伸縮性。默認(rèn)情況下,大多數(shù)這些改進(jìn)都已啟用。但是,存在可能顯著影響性能的編譯時(shí)和運(yùn)行時(shí)配置選擇。本文檔介紹了服務(wù)器管理員可以配置的選項(xiàng),以調(diào)整Apache 2.x安裝的性能。其中一些配置選項(xiàng)使httpd能夠更好地利用硬件和操作系統(tǒng)的功能,而其他配置選項(xiàng)則允許管理員交換功能以提高速度。

硬件和操作系統(tǒng)問(wèn)題

影響Web服務(wù)器性能的最大硬件問(wèn)題是服務(wù)器的內(nèi)存(RAM)。網(wǎng)絡(luò)服務(wù)器永遠(yuǎn)不應(yīng)該交換,因?yàn)榻粨Q會(huì)增加每個(gè)請(qǐng)求的延遲超出用戶(hù)認(rèn)為“足夠快”的點(diǎn)。這會(huì)導(dǎo)致用戶(hù)點(diǎn)擊停止并重新加載,從而進(jìn)一步增加負(fù)載。您可以而且應(yīng)該控制MaxRequestWorkers設(shè)置,以便您的服務(wù)器不會(huì)產(chǎn)生太多的子節(jié)點(diǎn)以便它開(kāi)始交換。執(zhí)行此操作的過(guò)程很簡(jiǎn)單:通過(guò)頂級(jí)工具查看流程列表,確定平均Apache流程的大小,并將其劃分為總可用內(nèi)存,為其他流程留出一些空間。

除此之外,其余的是平凡的:獲得足夠快的CPU,足夠快的網(wǎng)卡和足夠快的磁盤(pán),其中“足夠快”是需要通過(guò)實(shí)驗(yàn)確定的東西。

操作系統(tǒng)的選擇主要取決于管理員的問(wèn)題。但是一些經(jīng)證明通用的指南是:

  • 運(yùn)行選擇的操作系統(tǒng)的最新穩(wěn)定版本和修補(bǔ)程序級(jí)別。近年來(lái),許多OS供應(yīng)商已經(jīng)為其TCP堆棧和線(xiàn)程庫(kù)引入了顯著的性能改進(jìn)。
  • 如果操作系統(tǒng)支持sendfile(2)系統(tǒng)調(diào)用,請(qǐng)確保安裝啟用它所需的版本和/或修補(bǔ)程序。(例如,使用Linux,這意味著使用Linux 2.4或更高版本。對(duì)于Solaris 8的早期版本,您、可能需要應(yīng)用補(bǔ)丁。)在可用的系統(tǒng)上,sendfile使Apache 2能夠以更低的速度更快地提供靜態(tài)內(nèi)容 CPU利用率。

運(yùn)行時(shí)配置問(wèn)題

HostnameLookups和其他DNS注意事項(xiàng)

在Apache 1.3之前,HostnameLookups默認(rèn)為On。這會(huì)增加每個(gè)請(qǐng)求的延遲,因?yàn)樗枰谡?qǐng)求完成之前完成DNS查找。在Apache 1.3中,此設(shè)置默認(rèn)為關(guān)閉。如果您需要將日志文件中的地址解析為主機(jī)名,請(qǐng)使用Apache附帶的logresolve程序,或者可用的眾多日志報(bào)告程序包之一。

建議您在生產(chǎn)Web服務(wù)器計(jì)算機(jī)以外的某臺(tái)計(jì)算機(jī)上對(duì)日志文件進(jìn)行此類(lèi)后處理,以使此活動(dòng)不會(huì)對(duì)服務(wù)器性能產(chǎn)生負(fù)面影響。

如果使用域名允許或域名指令拒絕(即使用主機(jī)名或域名,而不是IP地址),那么您將需要付出兩次DNS查詢(xún)(反向,然后進(jìn)行正向查找以確保反過(guò)來(lái)沒(méi)有被欺騙)。因此,為了獲得最佳性能,請(qǐng)?jiān)谑褂眠@些指令時(shí)使用IP地址而不是名稱(chēng)(如果可能)。

請(qǐng)注意,可以對(duì)指令進(jìn)行范圍限定,例如在<Location "/server-status">部分中。在這種情況下,DNS查找僅在符合條件的請(qǐng)求上執(zhí)行。這是一個(gè)禁用除.html和.cgi文件之外的查找的示例:

HostnameLookups off
<Files ~ "\.(html|cgi)$">
  HostnameLookups on
</Files>
Shell

但即使如此,如果只需要在一些CGI中使用DNS名稱(chēng),可以考慮在需要它的特定CGI中進(jìn)行g(shù)ethostbyname調(diào)用。

FollowSymLinks和SymLinksIfOwnerMatch無(wú)論您的URL空間中沒(méi)有Options FollowSymLinks,或者都有選項(xiàng)SymLinksIfOwnerMatch,Apache都需要發(fā)出額外的系統(tǒng)調(diào)用來(lái)檢查符號(hào)鏈接。(每個(gè)文件名組件一次額外調(diào)用。)例如,如果配置有:

DocumentRoot "/www/htdocs"
<Directory "/">
  Options SymLinksIfOwnerMatch
</Directory>
Shell

并且對(duì)URI /index.html發(fā)出請(qǐng)求,然后Apache將在/www,/www/htdocs和/www/htdocs/index.html上執(zhí)行l(wèi)stat(2)。這些lstats的結(jié)果永遠(yuǎn)不會(huì)被緩存,因此它們將在每個(gè)請(qǐng)求中發(fā)生。如果真的想要符號(hào)鏈接安全檢查,可以這樣做:

DocumentRoot "/www/htdocs"
<Directory "/">
  Options FollowSymLinks
</Directory>

<Directory "/www/htdocs">
  Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory>
Shell

這至少避免了對(duì)DocumentRoot路徑的額外檢查。請(qǐng)注意,如果文檔根目錄之外有任何Alias或RewriteRule路徑,則需要添加類(lèi)似的部分。為了獲得最高性能,并且沒(méi)有符號(hào)鏈接保護(hù),請(qǐng)?jiān)谌魏蔚胤皆O(shè)置FollowSymLinks,并且永遠(yuǎn)不要設(shè)置SymLinksIfOwnerMatch。

AllowOverride無(wú)論您在URL空間中允許覆蓋(通常是.htaccess文件),Apache都會(huì)嘗試為每個(gè)文件名組件打開(kāi).htaccess。例如,

DocumentRoot "/www/htdocs"
<Directory "/">
  AllowOverride all
</Directory>
Shell

并且請(qǐng)求URI /index.html。然后Apache將嘗試打開(kāi)/.htaccess,/www/.htaccess和/www/htdocs/.htaccess。解決方案類(lèi)似于之前的Options FollowSymLinks案例。為獲得最高性能,請(qǐng)?jiān)谖募到y(tǒng)中的所有位置使用AllowOverride None。

協(xié)商

盡可能避免內(nèi)容協(xié)商。在實(shí)踐中,協(xié)商的好處超過(guò)了性能帶來(lái)的好處。有一種情況可以加快服務(wù)器的速度。使用如下的通配符并不是一個(gè)好的方法:

DirectoryIndex index
Shell

應(yīng)該使用完整的選項(xiàng)列表:

DirectoryIndex index.cgi index.pl index.shtml index.html
Shell

內(nèi)存映射在Apache 2.x需要查看正在傳遞的文件的內(nèi)容的情況下 - 例如,在執(zhí)行服務(wù)器端包含處理時(shí) - 如果操作系統(tǒng)支持某種形式的mmap,它通常會(huì)對(duì)文件進(jìn)行內(nèi)存映射(2)。

在某些平臺(tái)上,此內(nèi)存映射可提高性能。但是,有些情況下內(nèi)存映射會(huì)損害httpd的性能甚至穩(wěn)定性:

  • 在某些操作系統(tǒng)上,當(dāng)CPU數(shù)量增加時(shí),mmap不會(huì)像read(2)那樣擴(kuò)展。例如,在多處理器Solaris服務(wù)器上,當(dāng)禁用mmap時(shí),Apache 2.x有時(shí)會(huì)更快地提供服務(wù)器解析的文件。
  • 如果內(nèi)存映射位于NFS掛載的文件系統(tǒng)上的文件,并且另一個(gè)NFS客戶(hù)端計(jì)算機(jī)上的進(jìn)程刪除或截?cái)嘣撐募瑒t下次嘗試訪問(wèn)映射文件內(nèi)容時(shí),進(jìn)程可能會(huì)收到總線(xiàn)錯(cuò)誤。

對(duì)于適用這些因素之一的安裝,應(yīng)使用EnableMMAP off禁用已傳遞文件的內(nèi)存映射。(注意:可以在每個(gè)目錄的基礎(chǔ)上覆蓋此指令。)

Sendfile在Apache 2.x可以忽略要傳遞的文件內(nèi)容的情況下 - 例如,在提供靜態(tài)文件內(nèi)容時(shí) - 如果操作系統(tǒng)支持sendfile(2)操作,它通常會(huì)對(duì)文件使用內(nèi)核sendfile支持。

在大多數(shù)平臺(tái)上,使用sendfile通過(guò)消除單獨(dú)的讀取和發(fā)送機(jī)制來(lái)提高性能。但是,有些情況下使用sendfile會(huì)損害httpd的穩(wěn)定性:

某些平臺(tái)可能已經(jīng)破壞了構(gòu)建系統(tǒng)未檢測(cè)到的sendfile支持,特別是如果二進(jìn)制文件是在另一個(gè)盒子上構(gòu)建并移動(dòng)到這樣一臺(tái)具有損壞的sendfile支持的機(jī)器上的話(huà)。

使用NFS掛載的文件系統(tǒng),內(nèi)核可能無(wú)法通過(guò)其自己的緩存可靠地提供網(wǎng)絡(luò)文件。

進(jìn)程創(chuàng)建在Apache 1.3之前,MinSpareServers,MaxSpareServers和StartServers設(shè)置都對(duì)基準(zhǔn)測(cè)試結(jié)果產(chǎn)生了極大的影響。特別是,Apache需要一個(gè)“加速”期,以便達(dá)到足以服務(wù)于所應(yīng)用的負(fù)載的多個(gè)子項(xiàng)。初始產(chǎn)生StartServers子項(xiàng)后,每秒只會(huì)創(chuàng)建一個(gè)子項(xiàng)來(lái)滿(mǎn)足MinSpareServers設(shè)置。因此,一個(gè)服務(wù)器被100個(gè)并發(fā)客戶(hù)端訪問(wèn),使用默認(rèn)的StartServers為5將需要95秒的時(shí)間來(lái)產(chǎn)生足夠的子進(jìn)程來(lái)處理負(fù)載。這在實(shí)際服務(wù)器上的實(shí)際工作正常,因?yàn)樗鼈儾粫?huì)經(jīng)常重啟。但它的基準(zhǔn)測(cè)試確實(shí)很差,可能只運(yùn)行十分鐘。

實(shí)施每秒一次的規(guī)則是為了避免在新子項(xiàng)啟動(dòng)的情況下淹沒(méi)機(jī)器。如果機(jī)器忙于產(chǎn)生子項(xiàng),則無(wú)法提供服務(wù)請(qǐng)求。但它對(duì)Apache的感知性能產(chǎn)生了如此巨大的影響,必須予以取代。從Apache 1.3開(kāi)始,代碼將放寬每秒一次的規(guī)則。它將產(chǎn)生一個(gè),等待一秒,然后產(chǎn)生兩個(gè),等待一秒,然后產(chǎn)生四個(gè),它將以指數(shù)方式繼續(xù),直到它每秒產(chǎn)生32個(gè)子項(xiàng)。只要滿(mǎn)足MinSpareServers設(shè)置,它就會(huì)停止。

這似乎足夠響應(yīng),幾乎沒(méi)有必要扭轉(zhuǎn)MinSpareServers,MaxSpareServers和StartServers旋鈕。當(dāng)每秒生成4個(gè)以上的子節(jié)點(diǎn)時(shí),將向ErrorLog發(fā)送一條消息。

與進(jìn)程創(chuàng)建相關(guān)的是由MaxConnectionsPerChild設(shè)置引起的進(jìn)程死亡。默認(rèn)情況下,它的值是0,這意味著每個(gè)孩子處理的連接數(shù)沒(méi)有限制。如果您的配置當(dāng)前設(shè)置為某個(gè)非常低的數(shù)字,例如30,您可能希望顯著提高它。如果運(yùn)行的是SunOS或舊版本的Solaris,請(qǐng)將此限制為10000左右,因?yàn)樘呖赡軐?dǎo)致內(nèi)存泄漏。

編譯時(shí)配置問(wèn)題

選擇MPMApache 2.x支持可插入的并發(fā)模型,稱(chēng)為多處理模塊(MPM)。構(gòu)建Apache時(shí),必須選擇要使用的MPM。某些平臺(tái)有特定于平臺(tái)的MPM:mpm_netware,mpmt_os2和mpm_winnt。對(duì)于一般的Unix類(lèi)型系統(tǒng),有幾個(gè)MPM可供選擇。MPM的選擇會(huì)影響httpd的速度和可擴(kuò)展性:

  • worker MPM使用多個(gè)子進(jìn)程,每個(gè)進(jìn)程有多個(gè)線(xiàn)程。每個(gè)線(xiàn)程一次處理一個(gè)連接。對(duì)于高流量服務(wù)器,worker通常是一個(gè)不錯(cuò)的選擇,因?yàn)樗萷refork MPM具有更小的內(nèi)存占用。
  • 事件MPM像Worker MPM一樣具有線(xiàn)程,但旨在允許通過(guò)將一些處理工作傳遞給支持線(xiàn)程來(lái)同時(shí)提供更多請(qǐng)求,從而釋放主線(xiàn)程以處理新請(qǐng)求。
  • prefork MPM使用多個(gè)子進(jìn)程,每個(gè)進(jìn)程只有一個(gè)線(xiàn)程。每個(gè)進(jìn)程一次處理一個(gè)連接。在許多系統(tǒng)上,prefork的速度與worker相當(dāng),但它使用更多的內(nèi)存。在某些情況下,Prefork的無(wú)線(xiàn)設(shè)計(jì)優(yōu)于worker:它可以與非線(xiàn)程安全的第三方模塊一起使用,并且在具有較差線(xiàn)程調(diào)試支持的平臺(tái)上更容易調(diào)試。

模塊

由于內(nèi)存使用是性能中非常重要的考慮因素,因此您應(yīng)該嘗試消除實(shí)際上未使用的模塊。如果您已將模塊構(gòu)建為DSO,則消除模塊只需注釋掉該模塊的相關(guān)LoadModule指令即可。這使您可以嘗試刪除模塊,并查看您的網(wǎng)站是否仍然在沒(méi)有這些模塊的情況下運(yùn)行。

另一方面,如果您將模塊靜態(tài)鏈接到Apache二進(jìn)制文件中,則需要重新編譯Apache以刪除不需要的模塊。

當(dāng)然,這里出現(xiàn)的一個(gè)相關(guān)問(wèn)題是,您列出需要哪些模塊,哪些模塊不需要。當(dāng)然,這里的答案因網(wǎng)站而異。但是,您可以獲得的最小模塊列表往往包括mod_mime,mod_dir和mod_log_config。mod_log_config當(dāng)然是可選的,因?yàn)榭梢赃\(yùn)行沒(méi)有日志文件的網(wǎng)站。但是,不建議這樣做。

原子操作

一些模塊,例如mod_cache和worker MPM的最新開(kāi)發(fā)版本,使用APR的原子API。此API提供可用于輕量級(jí)線(xiàn)程同步的原子操作。

默認(rèn)情況下,APR使用每個(gè)目標(biāo)OS/CPU平臺(tái)上可用的最有效機(jī)制來(lái)實(shí)現(xiàn)這些操作。例如,許多現(xiàn)代CPU具有在硬件中執(zhí)行原子比較和交換(CAS)操作的指令。但是,在某些平臺(tái)上,APR默認(rèn)使用較慢的基于互斥鎖的原子API實(shí)現(xiàn),以確保與缺少此類(lèi)指令的舊CPU模型兼容。如果要為其中一個(gè)平臺(tái)構(gòu)建Apache,并且計(jì)劃僅在較新的CPU上運(yùn)行,則可以通過(guò)使用--enable-nonportable-atomics選項(xiàng)配置Apache來(lái)在構(gòu)建時(shí)選擇更快的原子實(shí)現(xiàn):

./buildconf
./configure --with-mpm=worker --enable-nonportable-atomics=yes
Shell

mod_status和ExtendedStatus On

如果包含mod_status并且在構(gòu)建和運(yùn)行Apache時(shí)也設(shè)置了ExtendedStatus On,那么在每次請(qǐng)求時(shí),Apache都會(huì)執(zhí)行兩次調(diào)用gettimeofday(2)(或者根據(jù)您的操作系統(tǒng)的時(shí)間(2))和(1.3之前)幾次額外的調(diào)用time(2)。這一切都已完成,以便狀態(tài)報(bào)告包含時(shí)間指示。為獲得最高性能,請(qǐng)關(guān)閉ExtendedStatus(這是默認(rèn)設(shè)置)。

接受序列化 - 單Socket

以上對(duì)于多個(gè)套接字服務(wù)器來(lái)說(shuō)很好,但是單個(gè)套接字服務(wù)器呢?從理論上講,他們不應(yīng)該遇到任何同樣的問(wèn)題,因?yàn)樗械淖泳€(xiàn)程都可以阻止accept()直到連接到來(lái),并且不會(huì)產(chǎn)生饑餓。在實(shí)踐中,這隱藏了上面在非阻塞解決方案中討論的幾乎相同的“旋轉(zhuǎn)”行為。大多數(shù)TCP堆棧的實(shí)現(xiàn)方式,內(nèi)核實(shí)際上喚醒了單個(gè)連接到達(dá)時(shí)阻塞的所有進(jìn)程。其中一個(gè)進(jìn)程獲取連接并返回用戶(hù)空間。其余的東西在內(nèi)核中旋轉(zhuǎn),當(dāng)他們發(fā)現(xiàn)沒(méi)有連接時(shí)再回到睡眠狀態(tài)。這種旋轉(zhuǎn)對(duì)用戶(hù)土地代碼是隱藏的,但它仍然存在。這可能導(dǎo)致相同的負(fù)載尖峰浪費(fèi)行為,多個(gè)插座盒的非阻塞解決方案可以。

出于這個(gè)原因,我們發(fā)現(xiàn)如果我們甚至序列化單個(gè)插槽的情況,許多架構(gòu)表現(xiàn)得更“漂亮”。所以這實(shí)際上是幾乎所有情況下的默認(rèn)值。Linux下的粗略實(shí)驗(yàn)(雙Pentium pro 166 w / 128Mb RAM上的2.0.30)表明,單插槽的串行化使得非串行化單插槽的每秒請(qǐng)求數(shù)減少不到3%。但是,非序列化的單插槽在每個(gè)請(qǐng)求上顯示額外的100ms延遲。這種延遲可能是長(zhǎng)途線(xiàn)路上的沖洗,而且只是局域網(wǎng)上的一個(gè)問(wèn)題。如果要覆蓋單個(gè)套接字序列化,可以定義SINGLE_LISTEN_UNSERIALIZED_ACCEPT,然后單個(gè)套接字服務(wù)器根本不會(huì)序列化。

附錄:跟蹤的詳細(xì)分析

以下是Apache 2.0.38的系統(tǒng)調(diào)用跟蹤以及Solaris 8上的worker MPM。此跟蹤是使用以下方法收集的:

truss -l -p httpd_child_pid.
Shell

-l選項(xiàng)告訴truss記錄調(diào)用每個(gè)系統(tǒng)調(diào)用的LWP(輕量級(jí)進(jìn)程 - Solaris形式的內(nèi)核級(jí)線(xiàn)程)的ID。

其他系統(tǒng)可能具有不同的系統(tǒng)調(diào)用跟蹤實(shí)用程序,例如strace,ktrace或par。它們都產(chǎn)生類(lèi)似的輸出。

在此跟蹤中,客戶(hù)端已從httpd請(qǐng)求了一個(gè)10KB的靜態(tài)文件。具有內(nèi)容協(xié)商的非靜態(tài)請(qǐng)求或請(qǐng)求的痕跡看起來(lái)非常不同。

/67:    accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
/67:    accept(3, 0x00200BEC, 0x00200C0C, 1)            = 9
Shell

在此跟蹤中,偵聽(tīng)器線(xiàn)程在LWP#67中運(yùn)行。

/65:    lwp_park(0x00000000, 0)                         = 0
/67:    lwp_unpark(65, 1)                               = 0
Shell

在接受連接時(shí),偵聽(tīng)器線(xiàn)程喚醒工作線(xiàn)程以執(zhí)行請(qǐng)求處理。在此跟蹤中,處理請(qǐng)求的工作線(xiàn)程將映射到LWP#65。

/65:    getsockname(9, 0x00200BA4, 0x00200BC4, 1)       = 0
Shell

為了實(shí)現(xiàn)虛擬主機(jī),Apache需要知道用于接受連接的本地套接字地址。在許多情況下(例如,當(dāng)沒(méi)有虛擬主機(jī),或者使用沒(méi)有通配符地址的Listen指令時(shí)),可以消除此調(diào)用。但是還沒(méi)有做出這些優(yōu)化的努力。

/65:    brk(0x002170E8)                                 = 0
/65:    brk(0x002190E8)                                 = 0
Shell

brk()調(diào)用從堆中分配內(nèi)存。在系統(tǒng)調(diào)用跟蹤中很少見(jiàn)到這些,因?yàn)閔ttpd使用自定義內(nèi)存分配器(apr_pool和apr_bucket_alloc)進(jìn)行大多數(shù)請(qǐng)求處理。在此跟蹤中,httpd剛剛啟動(dòng),因此必須調(diào)用malloc()來(lái)獲取用于創(chuàng)建自定義內(nèi)存分配器的原始內(nèi)存塊。

/65:    fcntl(9, F_GETFL, 0x00000000)                   = 2
/65:    fstat64(9, 0xFAF7B818)                          = 0
/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
/65:    fstat64(9, 0xFAF7B818)                          = 0
/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
/65:    setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
/65:    fcntl(9, F_SETFL, 0x00000082)                   = 0
Shell

接下來(lái),worker 線(xiàn)程以非阻塞模式將連接放入客戶(hù)端(文件描述符9)。setsockopt()和getsockopt()調(diào)用是Solaris的libc如何在套接字上處理fcntl()的副作用。

/65:    read(9, " G E T   / 1 0 k . h t m".., 8000)     = 97
Shell

worker線(xiàn)程從客戶(hù)端讀取請(qǐng)求。

/65:    stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
/65:    open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10
Shell

此httpd已使用Options FollowSymLinks和AllowOverride None進(jìn)行配置。因此,它不需要lstat()導(dǎo)致所請(qǐng)求文件的路徑中的每個(gè)目錄,也不需要檢查.htaccess文件。它只是調(diào)用stat()來(lái)驗(yàn)證文件:1)是否存在,2)是常規(guī)文件,而不是目錄。

/65:    sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C)      = 10269
Shell

在此示例中,httpd能夠使用單個(gè)sendfilev()系統(tǒng)調(diào)用發(fā)送HTTP響應(yīng)頭和所請(qǐng)求的文件。Sendfile語(yǔ)義因操作系統(tǒng)而異。在某些其他系統(tǒng)上,必須執(zhí)行write()或writev()調(diào)用以在調(diào)用sendfile()之前發(fā)送標(biāo)頭。

/65:    write(4, " 1 2 7 . 0 . 0 . 1   -  ".., 78)      = 78
Shell

此write()調(diào)用在訪問(wèn)日志中記錄請(qǐng)求。請(qǐng)注意,此跟蹤中缺少的一件事是time()調(diào)用。與Apache 1.3不同,Apache 2.x使用gettimeofday()來(lái)查找時(shí)間。在某些操作系統(tǒng)(如Linux或Solaris)上,gettimeofday具有優(yōu)化的實(shí)現(xiàn),不需要像典型系統(tǒng)調(diào)用那樣多的開(kāi)銷(xiāo)。

/65:    shutdown(9, 1, 1)                               = 0
/65:    poll(0xFAF7B980, 1, 2000)                       = 1
/65:    read(9, 0xFAF7BC20, 512)                        = 0
/65:    close(9)                                        = 0
Shell

worker 線(xiàn)程會(huì)延遲關(guān)閉連接。

/65:    close(10)                                       = 0
/65:    lwp_park(0x00000000, 0)         (sleeping...)
Shell

最后,工作線(xiàn)程關(guān)閉它剛剛傳遞的文件并阻塞,直到偵聽(tīng)器為其分配另一個(gè)連接。

/67:    accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)
Shell

同時(shí),監(jiān)聽(tīng)器線(xiàn)程一旦將此連接分派給工作線(xiàn)程,就能夠接受另一個(gè)連接(受制于工作者M(jìn)PM中的某些流控制邏輯,如果所有可用工作者都忙,則會(huì)限制監(jiān)聽(tīng)器)。雖然從這個(gè)跟蹤中看不出來(lái),但是下一個(gè)accept()可以(并且通常在高負(fù)載條件下)與工作線(xiàn)程處理剛剛接受的連接并行發(fā)生。




以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)