這篇文章將討論如何調(diào)優(yōu)web服務(wù)器和代理服務(wù)器,并采用科學(xué)的方法,將它們逐一應(yīng)用測(cè)量效果,終確定是否真的對(duì)所處的環(huán)境有用。
這不是一篇關(guān)于Linux性能的文章,盡管它大量引用了bcc工具、eBPF和perf,但不要誤以為是使用性能分析工具的全面指南。如果你想了解更多關(guān)于他們的信息,可以通過(guò)Brendan Gregg的博客閱讀。
這也不是一篇關(guān)于瀏覽器性能的文章。當(dāng)介紹與延遲相關(guān)的優(yōu)化時(shí),會(huì)涉及到客戶端的性能,但只是短暫的。如果你想知道更多這方面的,可以閱讀Ilya Grigorik的高性能瀏覽器網(wǎng)絡(luò)。
后,這也不是關(guān)于TLS(傳輸層安全協(xié)議)的佳實(shí)踐編譯,盡管會(huì)提到TLS庫(kù)及其設(shè)置,但那是為了評(píng)估每種方法的性能和安全性。可以使用Qualys SSL測(cè)試,以驗(yàn)證網(wǎng)絡(luò)終端與當(dāng)前的佳實(shí)踐,如果想了解更多關(guān)于TLS的信息,請(qǐng)考慮閱讀Feisty Duck Bulletproof TLS Newsletter。
文章將討論系統(tǒng)不同層級(jí)的效率/性能優(yōu)化。從硬件和驅(qū)動(dòng)程序的低級(jí)別開(kāi)始:這些調(diào)優(yōu)可以應(yīng)用到幾乎任何高負(fù)載服務(wù)器上。然后將轉(zhuǎn)移到linux內(nèi)核及其TCP/IP協(xié)議棧:這些是在任何一個(gè)TCP-heavy盒子上嘗試的旋鈕。后將討論庫(kù)和應(yīng)用程序級(jí)別的調(diào)優(yōu),它們主要適用于一般的web服務(wù)器和nginx服務(wù)器。
對(duì)于每一個(gè)潛在的優(yōu)化領(lǐng)域,將嘗試提供一些關(guān)于延遲/吞吐量權(quán)衡(如果有的話)的背景知識(shí),以及監(jiān)控指導(dǎo)方針,后建議對(duì)不同的工作負(fù)載作調(diào)整。
對(duì)于良好的非對(duì)稱(chēng)RSA/EC性能,具有至少AVX2(AVX2 in /proc/ cpuinfo)支持的處理器,好是具有大型整數(shù)算術(shù)能力硬件(bmi和adx)的處理器。而對(duì)于對(duì)稱(chēng)的情況,應(yīng)該找AES ciphers和AVX512的ChaCha+Poly。英特爾通過(guò)OpenSSL 1.0.2對(duì)不同的硬件產(chǎn)品進(jìn)行了性能比較,說(shuō)明了這些硬件卸載的影響。
CPU延遲敏感的用例,如路由選擇,減少NUMA的節(jié)點(diǎn)和禁用HT會(huì)有幫助。擁有更多內(nèi)核意味著高吞吐量的任務(wù)會(huì)處理得更好,并且將從超線程(除非它們是緩存綁定)中受益,而且通常不會(huì)過(guò)多地關(guān)心NUMA。
具體地說(shuō),如果走英特爾的路線,至少需要haswell或broadwell架構(gòu)的處理器與合適的Skylake CPUs。如果采用AMD,那么EPYC相當(dāng)不錯(cuò)。
至少需要10G網(wǎng)卡,好是25G。如果想要通過(guò)TLS單個(gè)服務(wù)器達(dá)到更大的傳輸,這里所描述的調(diào)優(yōu)是不夠的,可能需要將TLS構(gòu)建到內(nèi)核級(jí)別(例如FreeBSD,Linux)。
在軟件方面,應(yīng)該尋找具有活動(dòng)郵件列表和用戶社區(qū)的開(kāi)源驅(qū)動(dòng)程序。如果涉及到調(diào)試與驅(qū)動(dòng)相關(guān)的問(wèn)題,這將是非常重要的。
選擇的經(jīng)驗(yàn)法則是,延遲敏感的任務(wù)需要更快的內(nèi)存,而吞吐量敏感的任務(wù)需要更多的內(nèi)存。
這取決于緩沖/緩存的需求,如果要緩存大量的內(nèi)容,應(yīng)該選擇基于flash的存儲(chǔ)。有些甚至采用了專(zhuān)門(mén)的flash友好文件系統(tǒng)(通常是日志結(jié)構(gòu)的),但是它們并不總是比普通的ext4/xfs性能更好。
無(wú)論如何,注意不要因?yàn)橥泦⒂肨RIM或更新固件而燒穿了flash。
保持固件新,以避免痛苦和冗長(zhǎng)的故障排除會(huì)話。盡量保持新的CPU微碼,主板,NICs和ssd固件。這并不意味著要一直花錢(qián),經(jīng)驗(yàn)法則是把固件更新到上一個(gè)版本就行,除非它在新版本中修復(fù)了關(guān)鍵錯(cuò)誤,否則只要不要太落后就行。
更新規(guī)則和固件更新差不多,嘗試保持新。這里需要注意的是,如果可能的話,嘗試將內(nèi)核升級(jí)與驅(qū)動(dòng)程序更新解耦。例如,可以用DKMS打包驅(qū)動(dòng)程序,或者為使用的所有內(nèi)核版本預(yù)編譯驅(qū)動(dòng)程序。這樣當(dāng)更新內(nèi)核出現(xiàn)故障時(shí)不需要考慮驅(qū)動(dòng)程序。
在Ubuntu/Debian中,可以使用一些實(shí)用工具安裝linux工具包,但是現(xiàn)在只使用cpupower、turbostat和x86_energy_perf_policy即可。為了驗(yàn)證cpu相關(guān)的優(yōu)化,可以通過(guò)常用的負(fù)載生成工具對(duì)軟件進(jìn)行壓力測(cè)試(例如,Yandex使用Yandex.Tank)。下面是有一份來(lái)自NginxConf開(kāi)發(fā)者的演示,介紹了nginx加載測(cè)試的佳實(shí)踐:“nginx性能測(cè)試”。
使用這個(gè)工具比crawling /proc/更容易。要查看有關(guān)處理器及其頻率調(diào)控器的信息,請(qǐng)運(yùn)行以下代碼。
$ cpupower frequency-info ... driver: intel_pstate ... available cpufreq governors: performance powersave ... The governor "performance" may decide which speed to use ... boost state support:
Supported: yes
Active: yes
檢查是否啟用了Turbo Boost,對(duì)于Intel cpu確保運(yùn)行的是intel_pstate,而不是acpi-cpufreq或者pcc-cpufreq。如果堅(jiān)持使用acpic-cpufreq,那么應(yīng)該升級(jí)內(nèi)核,或者如果不能升級(jí),確保使用的是performance調(diào)控器。在使用intel_pstate運(yùn)行時(shí),powersave調(diào)控器也應(yīng)該運(yùn)行良好,但這一步需要自己去驗(yàn)證。
想看看空載時(shí)CPU到底發(fā)生了什么,可以使用turbostat直接查看處理器的MSRs,獲取電源、頻率和空閑狀態(tài)信息。
# turbostat --debug -P ... Avg_MHz Busy% ... CPU%c1 CPU%c3 CPU%c6 ... Pkg%pc2 Pkg%pc3 Pkg%pc6 ...
這里可以看到實(shí)際的CPU頻率(是的,/proc/cpuinfo欺騙了你),以及核心/包空閑狀態(tài)。
如果使用intel_pstate驅(qū)動(dòng)程序,CPU的空閑時(shí)間會(huì)比預(yù)想的要多,可以采取以下措施。
設(shè)置性能調(diào)節(jié)。
設(shè)置x86_energy_perf_policy性能。
或者,對(duì)于非常延遲的關(guān)鍵任務(wù),還可以這樣做。
采用/dev/cpu_dma_latency接口。
對(duì)于UDP流量,使用busy-polling方法。
更多關(guān)于處理器電源管理的信息,可以在2015年的LinuxCon Europe上由“Linux內(nèi)核”的Intel開(kāi)源技術(shù)中心發(fā)表的“Linux內(nèi)核中的平衡能力和性能”文章中了解到。
還可以通過(guò)在每個(gè)線程/流程上應(yīng)用CPU關(guān)聯(lián)性來(lái)降低延遲,例如nginx,它具有worker_cpu_affinity指令,可以自動(dòng)將每個(gè)web服務(wù)器進(jìn)程綁定到它自己的核心。這可以消除CPU遷移,減少緩存遺漏和頁(yè)面錯(cuò)誤,并稍微增加每個(gè)周期的指令數(shù)。所有這些都可以通過(guò)perf stat來(lái)驗(yàn)證。
遺憾的是,啟用親和性也會(huì)增加等待空閑CPU的時(shí)間,從而對(duì)性能產(chǎn)生負(fù)面影響。可以通過(guò)在pid上運(yùn)行runqlat來(lái)監(jiān)控。
usecs : count distribution 0 -> 1 : 819 | | 2 -> 3 : 58888 |****************************** | 4 -> 7 : 77984 |****************************************| 8 -> 15 : 10529 |***** | 16 -> 31 : 4853 |** | ... 4096 -> 8191 : 34 | | 8192 -> 16383 : 39 | | 16384 -> 32767 : 17 | |
如果看到多毫秒的延遲,那么除了nginx本身之外,服務(wù)器可能在處理其他很多的事,一旦關(guān)聯(lián)將增加延遲,而不是減少。
所有的mm/tunings通常都是非常具體的工作流,可以推薦的方法很少。
確定有所幫助的話,設(shè)置THP并進(jìn)行啟用,否則會(huì)適得其反得到一個(gè)數(shù)量級(jí)的減速,而不是20%的目標(biāo)延遲改進(jìn)。
針對(duì)單個(gè)NUMA節(jié)點(diǎn)設(shè)置vm.zone_reclaim_mode為0.## NUMA。
現(xiàn)代的CPU實(shí)際上包含多個(gè)獨(dú)立的CPU,它們通過(guò)高速互連和共享資源,從HT核心的L1緩存開(kāi)始,經(jīng)過(guò)包內(nèi)的L3高速緩存,再到內(nèi)存和套接字內(nèi)PCIe鏈路。這基本上就組成了NUMA,它具有快速互連的多個(gè)執(zhí)行和存儲(chǔ)單元。
對(duì)于NUMA的全面概述及其影響,可以參考Frank Denneman的“NUMA深入分析系列”。
對(duì)于NUMA長(zhǎng)話短說(shuō),可以進(jìn)行以下選擇:
選擇忽略,在BIOS中禁用它,或者在numactl –interleave=all下運(yùn)行軟件,可以得到一般的性能。
通過(guò)使用單節(jié)點(diǎn)服務(wù)器來(lái)替換它,就像Facebook和OCP Yosemite平臺(tái)一樣。
選擇接受,并優(yōu)化用戶和內(nèi)核空間中的CPU/內(nèi)存。
現(xiàn)在討論第三種選擇,因?yàn)榍皟煞N方法并沒(méi)有太多的優(yōu)化。
要合理地使用NUMA需要將每個(gè)NUMA節(jié)點(diǎn)視為一個(gè)單獨(dú)的服務(wù)器,對(duì)此應(yīng)該首先檢查拓?fù)浣Y(jié)構(gòu),可以通過(guò)numactl –hardware查看。
$ numactl --hardware available: 4 nodes (0-3)
node 0 cpus: 0 1 2 3 16 17 18 19 node 0 size: 32149 MB
node 1 cpus: 4 5 6 7 20 21 22 23 node 1 size: 32213 MB
node 2 cpus: 8 9 10 11 24 25 26 27 node 2 size: 0 MB
node 3 cpus: 12 13 14 15 28 29 30 31 node 3 size: 0 MB
node distances:
node 0 1 2 3 0: 10 16 16 16 1: 16 10 16 16 2: 16 16 10 16 3: 16 16 16 10
考慮的因素有:
這是一個(gè)非常糟糕的用例,因?yàn)樗?個(gè)節(jié)點(diǎn)同時(shí)沒(méi)有附加內(nèi)存的節(jié)點(diǎn)。在不犧牲系統(tǒng)一半內(nèi)核的情況下,很難把每個(gè)節(jié)點(diǎn)都當(dāng)作獨(dú)立的服務(wù)器來(lái)處理。
可以通過(guò)使用numastat來(lái)驗(yàn)證:
$ numastat -n -c Node 0 Node 1 Node 2 Node 3 Total -------- -------- ------ ------ -------- Numa_Hit 26833500 11885723 0 0 38719223 Numa_Miss 18672 8561876 0 0 8580548 Numa_Foreign 8561876 18672 0 0 8580548 Interleave_Hit 392066 553771 0 0 945836 Local_Node 8222745 11507968 0 0 19730712 Other_Node 18629427 8939632 0 0 27569060
也可以以/proc/meminfo格式要求numastat輸出每個(gè)節(jié)點(diǎn)的內(nèi)存使用統(tǒng)計(jì)信息。
$ numastat -m -c
Node 0 Node 1 Node 2 Node 3 Total
------ ------ ------ ------ -----
MemTotal 32150 32214 0 0 64363 MemFree 462 5793 0 0 6255 MemUsed 31688 26421 0 0 58109 Active 16021 8588 0 0 24608 Inactive 13436 16121 0 0 29557 Active(anon) 1193 970 0 0 2163 Inactive(anon) 121 108 0 0 229 Active(file) 14828 7618 0 0 22446 Inactive(file) 13315 16013 0 0 29327 ... FilePages 28498 23957 0 0 52454 Mapped 131 130 0 0 261 AnonPages 962 757 0 0 1718 Shmem 355 323 0 0 678 KernelStack 10 5 0 0 16
現(xiàn)在看一個(gè)更簡(jiǎn)單的拓?fù)鋱D。
$ numactl --hardware available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 node 0 size: 46967 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31 node 1 size: 48355 MB
由于節(jié)點(diǎn)基本是對(duì)稱(chēng)的,可以通過(guò)numactl –cpunodebind=X –membind=X將應(yīng)用程序的實(shí)例綁定到對(duì)應(yīng)的NUMA節(jié)點(diǎn),然后在另一個(gè)端口上公開(kāi)它,這樣就可以通過(guò)使用兩個(gè)節(jié)點(diǎn)獲得更好的吞吐量,通過(guò)保留內(nèi)存位置獲取更好的延遲。
通過(guò)對(duì)內(nèi)存操作的延遲來(lái)驗(yàn)證NUMA的放置效率,例如使用bcc的funclatency來(lái)度量?jī)?nèi)存重操作的延遲,像memmove。
在內(nèi)核方面,使用perf stat來(lái)觀察效率,并查詢(xún)相應(yīng)的內(nèi)存和調(diào)度器事件。
# perf stat -e sched:sched_stick_numa,sched:sched_move_numa,sched:sched_swap_numa,migrate:mm_migrate_pages,minor-faults -p PID ... 1 sched:sched_stick_numa 3 sched:sched_move_numa 41 sched:sched_swap_numa 5,239 migrate:mm_migrate_pages 50,161 minor-faults
對(duì)network-heavy工作負(fù)載,后一點(diǎn)與numa相關(guān)的優(yōu)化來(lái)自于一個(gè)事實(shí),即網(wǎng)絡(luò)適配器是一個(gè)PCIe設(shè)備,每個(gè)設(shè)備都綁定到自己的numa節(jié)點(diǎn),因此在與網(wǎng)絡(luò)通信時(shí),一些cpu的延遲時(shí)間會(huì)較低。討論NIC和CPU親和力時(shí)將涉及到優(yōu)化可以應(yīng)用到哪些地方,現(xiàn)在先說(shuō)一說(shuō)PCIe。
通常情況下,除非出現(xiàn)某種硬件故障,否則不需要深入地進(jìn)行PCIe故障排除。因此只需創(chuàng)建“鏈接寬度”、“鏈接速度”,并盡可能為PCIe設(shè)備創(chuàng)建RxErr/BadTLP提醒。當(dāng)硬件損壞或PCIe協(xié)商失敗,這將節(jié)省故障排除時(shí)間。可以使用lspci達(dá)到目的。
# lspci -s 0a:00.0 -vvv ... LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM L1, Exit Latency L0s <2us, L1 <16us LnkSta: Speed 8GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt- ... Capabilities: [100 v2] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- ... UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- ... UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- ... CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
PCIe可能會(huì)成為一個(gè)瓶頸,如果存在多個(gè)高速設(shè)備競(jìng)爭(zhēng)帶寬(例如將快速網(wǎng)絡(luò)與快速存儲(chǔ)結(jié)合起來(lái)),那么可能需要在cpu之間物理地切分PCI總線設(shè)備以獲得大的吞吐量。
圖片來(lái)源:。
Mellanox網(wǎng)站上有篇文章“理解PCIe配置的大性能”,更深入的介紹了PCIe配置,對(duì)于高速傳輸中出現(xiàn)卡頓和操作系統(tǒng)之間的數(shù)據(jù)包丟失會(huì)有所幫助。
英特爾公司表示,有時(shí)PCIe的權(quán)力管理(ASPM)可能導(dǎo)致更高的延遲,從而導(dǎo)致更高的包損失,但可以通過(guò)向內(nèi)核cmdline添加pcie_aspm=off禁用它。
開(kāi)始之前需要說(shuō)明的是,Intel和Mellanox都有自己的性能調(diào)優(yōu)指南,無(wú)論選擇哪種供應(yīng)商,都有助于了解它們。同時(shí),驅(qū)動(dòng)程序通常也有自己的README和一套實(shí)用工具。
下一個(gè)需要閱讀的是操作系統(tǒng)的手冊(cè),例如紅帽企業(yè)版Linux系統(tǒng)網(wǎng)絡(luò)性能調(diào)優(yōu)指南,它提到了下面的大多數(shù)優(yōu)化,甚至更多。
Cloudflare也提供了一篇關(guān)于在博客上調(diào)優(yōu)網(wǎng)絡(luò)堆棧的一部分的文章,盡管它主要是針對(duì)低延遲的用例。
在優(yōu)化網(wǎng)絡(luò)適配器時(shí),ethtool將提供很好的幫助。
注意,如果正在使用一個(gè)新的內(nèi)核,應(yīng)該在userland中添加一些部分,比如對(duì)于網(wǎng)絡(luò)操作,可能需要新的:ethtool,iproute2,以及iptables/nftables包。
可以通過(guò)ethtool -s了解網(wǎng)卡信息。
$ ethtool -S eth0 | egrep 'miss|over|drop|lost|fifo' rx_dropped: 0 tx_dropped: 0 port.rx_dropped: 0 port.tx_dropped_link_down: 0 port.rx_oversize: 0 port.arq_overflows: 0
與NIC制造商進(jìn)行詳細(xì)的統(tǒng)計(jì)描述,例如Mellanox為他們提供了一個(gè)專(zhuān)門(mén)的wiki頁(yè)面。
內(nèi)核方面將看到/proc/interrupts、/proc/softirqs和/proc/net/softnet_stat。這里有兩個(gè)有用的bcc工具,hardirqs和softirqs。優(yōu)化網(wǎng)絡(luò)的目標(biāo)是在沒(méi)有數(shù)據(jù)包丟失的情況下,對(duì)系統(tǒng)進(jìn)行優(yōu)化,直至達(dá)到小的CPU使用量。
調(diào)優(yōu)通常從處理器之間的擴(kuò)展中斷開(kāi)始,具體怎么做取決于工作量。
為了獲取大吞吐量,可以在系統(tǒng)中的所有numa節(jié)點(diǎn)上分發(fā)中斷。
為了得到低延遲,可以將中斷限制為單個(gè)numa節(jié)點(diǎn)。要做到這一點(diǎn),可能需要減少隊(duì)列的數(shù)量,以適應(yīng)單個(gè)節(jié)點(diǎn)(這通常意味著用ethtool -L將它們的數(shù)量減少一半)。
供應(yīng)商通常提供腳本以達(dá)到目的,例如英特爾有set_irq_affinity。
網(wǎng)卡與內(nèi)核交換信息一般是通過(guò)一種叫做“環(huán)”的數(shù)據(jù)結(jié)構(gòu)來(lái)完成的,該數(shù)據(jù)結(jié)構(gòu)借助ethtool -g可以查看該“環(huán)”的當(dāng)前/大尺寸。
$ ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums: RX: 4096 TX: 4096 Current hardware settings: RX: 4096 TX: 4096
可以在預(yù)先設(shè)置的大值與-G之間作調(diào)整,一般來(lái)說(shuō)越大越好(特別是如果使用中斷合并時(shí)),因?yàn)樗鼘⒔o予更多的保護(hù)來(lái)防止突發(fā)事件和內(nèi)核內(nèi)的間斷,因此降低了由于沒(méi)有緩沖區(qū)空間/錯(cuò)過(guò)中斷而減少的數(shù)據(jù)包數(shù)量。但有幾點(diǎn)需要說(shuō)明:
中斷合并允許通過(guò)在一個(gè)中斷中聚合多個(gè)事件來(lái)延遲通知內(nèi)核的新事件。當(dāng)前設(shè)置可以通過(guò)ethtool -c來(lái)查看。
$ ethtool -c eth0
Coalesce parameters for eth0: ... rx-usecs: 50 tx-usecs: 50
可以使用靜態(tài)限制嚴(yán)格限制每秒中斷的大中斷數(shù),或者依賴(lài)硬件基于吞吐量自動(dòng)調(diào)整中斷率。
啟用合并(使用 -c)將增加延遲,并可能引發(fā)包丟失,所以需要避免它對(duì)延遲敏感。另一方面,完全禁用它可能導(dǎo)致中斷節(jié)流,從而影響性能。
現(xiàn)代網(wǎng)卡比較智能,可以將大量的工作轉(zhuǎn)移到硬件或仿真驅(qū)動(dòng)程序上。
所有可能的卸載都可以通過(guò)ethtool -k查看。
$ ethtool -k eth0
Features for eth0: ... tcp-segmentation-offload: on generic-segmentation-offload: on generic-receive-offload: on large-receive-offload: off [fixed]
在輸出中,所有不可調(diào)的卸載都采用[fixed]后綴標(biāo)記。
關(guān)于它們有很多討論,但這里有一些經(jīng)驗(yàn)法則。
不要啟用LRO,使用GRO代替。
要小心使用TSO,因?yàn)樗叨纫蕾?lài)于驅(qū)動(dòng)/固件的質(zhì)量。
不要在舊的內(nèi)核中啟用TSO/GSO,因?yàn)樗赡軙?huì)導(dǎo)致嚴(yán)重的緩存過(guò)滿。所有現(xiàn)代NICs都優(yōu)化了多核硬件,因此他們將包內(nèi)部拆分為虛擬隊(duì)列(通常是一個(gè)CPU)。當(dāng)它在硬件中完成時(shí),它被稱(chēng)為RSS,當(dāng)操作系統(tǒng)負(fù)責(zé)交叉cpu的負(fù)載平衡包時(shí),它被稱(chēng)為RPS(與TX-counterpart對(duì)應(yīng)的稱(chēng)為XPS)。當(dāng)操作系統(tǒng)試圖變得智能并路由到當(dāng)前正在處理該套接字的cpu時(shí),它被稱(chēng)為RFS。當(dāng)硬件實(shí)現(xiàn)該功能時(shí),它被稱(chēng)為“加速RFS”或簡(jiǎn)稱(chēng)“aRFS”。
以下是生產(chǎn)中的一些佳實(shí)踐。
如果正在使用新的25 G+硬件,它可能有足夠的隊(duì)列和一個(gè)巨大的間接表,以便能夠在所有的內(nèi)核中提供RSS。一些老的NICs只使用前16個(gè)cpu。
以下情況可以嘗試啟用RPS:
啟用導(dǎo)流器(或英特爾術(shù)語(yǔ)中的fdir)在應(yīng)用程序的目標(biāo)路由模式中是默認(rèn)操作,該應(yīng)用程序通過(guò)取樣包和轉(zhuǎn)向系統(tǒng)來(lái)實(shí)現(xiàn)aRFS,并將其控制在可能被處理的核心位置。它的統(tǒng)計(jì)數(shù)據(jù)也可以通過(guò)ethtool - s:$ ethtool - s eth0 |egrep “fdir” port.fdir_flush_cnt:0實(shí)現(xiàn)。
盡管英特爾聲稱(chēng)fdir在某些情況下提高了性能,但外部研究表明它也引發(fā)了多1%的包重新排序,這對(duì)TCP性能有很大的損害。因此可以測(cè)試一下,看看FD是否對(duì)工作負(fù)載有幫助,同時(shí)要注意TCPOFOQueue計(jì)數(shù)器。
對(duì)于Linux網(wǎng)絡(luò)堆棧的調(diào)優(yōu),有無(wú)數(shù)的書(shū)籍、視頻和教程??杀氖牵罅康摹皊ysctl.conf cargo-culting”隨之而來(lái),即使近的內(nèi)核版本不需要像10年前那樣多的調(diào)優(yōu),而且大多數(shù)新的TCP/IP特性在默認(rèn)情況下都是啟用和已調(diào)優(yōu)的,人們?nèi)匀辉趶?fù)制舊的已經(jīng)使用了2.6.18/2.6.32內(nèi)核的sysctls.conf。
為了驗(yàn)證與網(wǎng)絡(luò)相關(guān)的優(yōu)化效果,需要:
對(duì)于關(guān)于網(wǎng)絡(luò)優(yōu)化的信息來(lái)源,個(gè)人喜歡由CDN-folks進(jìn)行的會(huì)議討論,因?yàn)樗麄兺ǔV涝谧鍪裁?,比?span style="color:#337ab7;">LinuxCon在澳大利亞的快速發(fā)展。聽(tīng)Linux內(nèi)核開(kāi)發(fā)人員關(guān)于網(wǎng)絡(luò)的說(shuō)法也是很有啟發(fā)性的,例如netdevconf對(duì)話和NETCONF記錄。
通過(guò)PackageCloud深入到Linux網(wǎng)絡(luò)堆棧中時(shí)以下需要注意,特別是當(dāng)側(cè)重監(jiān)視而不是盲目的調(diào)優(yōu)時(shí)。
開(kāi)始之前再次重申:請(qǐng)升級(jí)內(nèi)核!有大量的新網(wǎng)絡(luò)堆棧改進(jìn),比如關(guān)于新的熱像:TSO自動(dòng)調(diào)整,F(xiàn)Q,步測(cè),TLP,和機(jī)架,但以后更多。通過(guò)升級(jí)到一個(gè)新的內(nèi)核,將得到一大堆拓展性改進(jìn),如刪除路由緩存、lockless偵聽(tīng)套接字、SO_REUSEPORT等等。
近的Linux網(wǎng)絡(luò)文章中非常顯目的是“讓Linux TCP快速運(yùn)行”。它通過(guò)將Linux sender-side TCP堆棧分解為功能塊,從而鞏固了Linux內(nèi)核的多年改進(jìn)。
公平隊(duì)列負(fù)責(zé)改善TCP流之間的公平性和減少行阻塞,這對(duì)包的下降率有積極的影響。以擁塞控制的速度設(shè)定數(shù)據(jù)包,以同樣的間隔時(shí)間間隔來(lái)設(shè)置數(shù)據(jù)包,從而進(jìn)一步減少數(shù)據(jù)包損失,終提高吞吐量。
附注一點(diǎn):在linux中,通過(guò)fq qdisc可以獲得公平隊(duì)列和pacing。不要誤以為這些是BBR的要求,它們都可以與CUBIC一同使用以減少15-20%的數(shù)據(jù)包損失,從而提高CCs上損失的吞吐量。只是不要在舊的內(nèi)核(低于3.19版本)中使用它,因?yàn)闀?huì)結(jié)束pacing pure ACKs,并破壞uploads/RPCs。
兩種方法都負(fù)責(zé)限制TCP堆棧中的緩沖,從而降低延遲,且不會(huì)犧牲吞吐量。
CC算法本身設(shè)計(jì)領(lǐng)域很廣,近年來(lái)圍繞它們進(jìn)行了大量的活動(dòng)。其中一些活動(dòng)被編纂為:tcp_cdg(CAIA)、tcp_nv(Facebook)和tcp_bbr(谷歌)。這里不會(huì)太深入地討論他們的內(nèi)部工作,先假設(shè)所有的人都依賴(lài)于延遲的增加而不是數(shù)據(jù)包的減少。
BBR可以說(shuō)是所有新的擁塞控制中,文檔完整、可測(cè)試和實(shí)用的?;舅枷胧墙⒁粋€(gè)基于包傳輸速率的網(wǎng)絡(luò)路徑模型,然后執(zhí)行控制循環(huán),大限度地提高帶寬,同時(shí)小化rtt。這正是代理堆棧中需要的。
來(lái)自BBR實(shí)驗(yàn)的初步數(shù)據(jù)顯示,文件下載速度有提升。
在東京的BBR實(shí)驗(yàn)6小時(shí):x軸表示時(shí)間,y軸表示客戶端下載速度。
需要強(qiáng)調(diào)的是有觀察到所有百分位數(shù)的速度都在增長(zhǎng),這不是后端修改引起。通常只會(huì)給p90+用戶帶來(lái)好處(互聯(lián)網(wǎng)連接速度快的用戶),因?yàn)槠渌腥硕际菐捪拗频?。網(wǎng)絡(luò)級(jí)的調(diào)優(yōu),比如改變擁塞控制,或者啟用FQ /pacing顯示用戶沒(méi)有帶寬限制,但是他們是“tcp - limited”。
如果想了解更多關(guān)于BBR的信息,APNIC有一個(gè)很好的入門(mén)級(jí)的BBR概述(它與基于損失的擁擠控制的對(duì)比)。關(guān)于BBR的更深入的信息,可以閱讀bbr-dev郵件列表檔案(它在頂部有許多有用的鏈接)。對(duì)擁塞控制感興趣的,可以關(guān)注網(wǎng)絡(luò)擁塞控制研究小組的有趣活動(dòng)。
關(guān)于擁塞控制已經(jīng)說(shuō)了很多,下面再次運(yùn)行新的內(nèi)核討論一下丟失檢測(cè)。那些新的啟發(fā)式方法,比如TLP和RACK,經(jīng)常被添加到TCP,而FACK和ER等舊的東西正在被淘汰。一旦添加,它們是默認(rèn)啟用的,因此在升級(jí)之后不需要調(diào)整任何系統(tǒng)設(shè)置。
用戶空間套接字api提供隱式緩沖,一旦被發(fā)送,就無(wú)法重新排序塊,因此在多路復(fù)用場(chǎng)景中(例如HTTP/2),可能導(dǎo)致HOL阻塞,以及h2優(yōu)先級(jí)反轉(zhuǎn)。TCP_NOTSENT_LOWAT套接字選項(xiàng)(和相應(yīng)的net.ipv4.tcp_notsent_lowat sysctl)被設(shè)計(jì)用來(lái)解決這個(gè)問(wèn)題,它設(shè)置了一個(gè)閾值,在這個(gè)閾值中,套接字會(huì)認(rèn)為自己是可寫(xiě)的(即epoll會(huì)對(duì)欺騙應(yīng)用程序)。從而可以解決使用HTTP/2優(yōu)先級(jí)的問(wèn)題,但它也可能對(duì)吞吐量產(chǎn)生負(fù)面影響。
在談到網(wǎng)絡(luò)優(yōu)化的時(shí)候,不能不提到關(guān)于sysctls的調(diào)優(yōu)。先從不熟悉的開(kāi)始。
- net.ipv4.tcp_tw_recycle=1——不要使用它——它已經(jīng)被NAT的用戶破壞了,但是如果升級(jí)內(nèi)核將有所改善。
- net.ipv4.tcp_timestamps=0——不要禁用它們,除非已知所有的副作用,而且可以接受它們。例如,一個(gè)不明顯的副作用是可以在syncookie上打開(kāi)窗口縮放和SACK選項(xiàng)。
對(duì)于sysctls需要使用:
同樣值得注意的是,有一份由curl的作者Daniel Stenberg編寫(xiě)的RFC草案,命名為HTTP的TCP調(diào)優(yōu),它試圖整理所有可能對(duì)HTTP有利的系統(tǒng)調(diào)優(yōu)。
就像內(nèi)核一樣,擁有新的用戶空間是非常重要的。從升級(jí)工具開(kāi)始,例如打包新版本的perf、bcc等。
一旦有了新的工具,就可以適當(dāng)?shù)卣{(diào)整和觀察系統(tǒng)的行為。這一部分主要依賴(lài)于通過(guò)perf top、on-CPU flamegraphs和來(lái)自bcc funclatency的臨時(shí)直方圖進(jìn)行on-cpu分析。
如果想要編譯硬件優(yōu)化的組件,那么擁有一個(gè)現(xiàn)代的編譯器工具鏈?zhǔn)潜夭豢缮俚?,這在許多web服務(wù)器通常使用的庫(kù)中也是存在的。
除了性能之外,新的編譯器具有新的安全特性(如-fstack-protector-strong或SafeStack),這些特性是想在邊緣網(wǎng)絡(luò)中應(yīng)用的?,F(xiàn)代工具鏈的另一個(gè)用例是,當(dāng)運(yùn)行測(cè)試工具時(shí),殺毒軟件(例如AddressSanitizer和friends)編譯的是二進(jìn)制文件。
推薦升級(jí)系統(tǒng)庫(kù),比如glibc,因?yàn)樵谄渌矫?,可能?huì)錯(cuò)過(guò)-lc、-lm、-lrt等低級(jí)功能中近存在的優(yōu)化。
通常,web服務(wù)器將負(fù)責(zé)壓縮。根據(jù)多少數(shù)據(jù)將通過(guò)代理,偶爾會(huì)在perf top看到zlib的符號(hào),例如:
# perf top ... 8.88% nginx [.] longest_match 8.29% nginx [.] deflate_slow 1.90% nginx [.] compress_block
在低級(jí)別上有一些優(yōu)化的方法:英特爾和Cloudflare,以及一個(gè)獨(dú)立的zlib-ng項(xiàng)目,都有他們的zlib forks,可以通過(guò)使用新的指令集提供更好的性能。
在討論優(yōu)化之前,我們主要是面向cpu的,但是現(xiàn)在換一個(gè)角度,討論與內(nèi)存相關(guān)的優(yōu)化。如果使用大量的Lua和FFI或第三方的重模塊來(lái)執(zhí)行它們自己的內(nèi)存管理,可能會(huì)由于碎片化而增加內(nèi)存使用。可以嘗試通過(guò)切換到j(luò)emalloc或tcmalloc來(lái)解決這個(gè)問(wèn)題。
使用自定義malloc有以下好處。
如果在nginx configs中使用許多復(fù)雜的正則表達(dá)式,或者嚴(yán)重依賴(lài)Lua,perf top會(huì)顯示與pcre相關(guān)的標(biāo)志。可以通過(guò)使用JIT編譯PCRE進(jìn)行優(yōu)化,也可以通過(guò)pcre_jit在nginx中啟用它。
通過(guò)查看火焰圖或者使用funclatency檢查優(yōu)化的結(jié)果。
# funclatency /srv/nginx-bazel/sbin/nginx:ngx_http_regex_exec -u ... usecs : count distribution 0 -> 1 : 1159 |********** | 2 -> 3 : 4468 |****************************************| 4 -> 7 : 622 |***** | 8 -> 15 : 610 |***** | 16 -> 31 : 209 |* | 32 -> 63 : 91 | |
如果在CDN前端的w/o邊緣終止TLS,那么TLS性能優(yōu)化的價(jià)值是非??捎^的。在討論調(diào)優(yōu)時(shí)主要關(guān)注服務(wù)器端效率。
因此需要決定的件事是使用哪些TLS庫(kù):Vanilla OpenSSL、OpenBSD LibreSSL或谷歌的BoringSSL。在選擇TLS庫(kù)的偏好之后,需要適當(dāng)?shù)貥?gòu)建它,例如,OpenSSL有一堆構(gòu)建時(shí)的啟發(fā)式,可以根據(jù)構(gòu)建環(huán)境進(jìn)行優(yōu)化;BoringSSL具有確定性的構(gòu)建,但遺憾的是它更保守,并且在默認(rèn)情況下禁用了一些優(yōu)化。無(wú)論如何,在這里優(yōu)先選擇現(xiàn)代的CPU,大多數(shù)TLS庫(kù)可以使用從AES-NI和SSE到ADX和AVX512的所有屬性??梢允褂脦в蠺LS庫(kù)的內(nèi)置性能測(cè)試,例如在BoringSSL案例中,內(nèi)置有bssl speed。
大多數(shù)性能不是來(lái)自已有的硬件,而是來(lái)自將要使用的cipher - suite,因此必須仔細(xì)地優(yōu)化它們。也需要知道這里的變化會(huì)影響web服務(wù)器的安全性——快的密碼套件不一定是好的。如果不確定要使用什么加密設(shè)置,Mozilla SSL配置生成器是一個(gè)很好的選擇。
如果服務(wù)處于邊緣,那么可能會(huì)觀察到相當(dāng)數(shù)量的TLS握手,因此CPU占用了大量的非對(duì)稱(chēng)密碼,這使它成為優(yōu)化的明顯目標(biāo)。
為了優(yōu)化服務(wù)器端CPU,可以切換到ECDSA certs,其速度通常比RSA快10倍,而且它們的體積要小得多,因此在出現(xiàn)包丟失時(shí)能加速握手。但是ECDSA也嚴(yán)重依賴(lài)于系統(tǒng)的隨機(jī)數(shù)生成器的質(zhì)量,所以如果使用的是OpenSSL,那么一定要有足夠的熵值(使用BoringSSL,不必?fù)?dān)心這一點(diǎn))。
附注一點(diǎn),越大并不總是越好,例如使用4096個(gè)RSA證書(shū)會(huì)降低10倍的性能。
$ bssl speed
Did 1517 RSA 2048 signing ... (1507.3 ops/sec)
Did 160 RSA 4096 signing ... (153.4 ops/sec)
更糟糕的是,小的也不一定是好的選擇:使用non-common p-224字段與更常見(jiàn)的p-256相比,會(huì)降低60%的性。
$ bssl speed
Did 7056 ECDSA P-224 signing ... (6831.1 ops/sec)
Did 17000 ECDSA P-256 signing ... (16885.3 ops/sec)
原則上常用的加密通常是優(yōu)的加密。
在使用RSA certs運(yùn)行適當(dāng)優(yōu)化的基于opentls的庫(kù)時(shí),可以在perf top:AVX2-capable看到以下的跟蹤信息,但不能使用ADX-capable盒子(例如Haswell)。
6.42% nginx [.] rsaz_1024_sqr_avx2 1.61% nginx [.] rsaz_1024_mul_avx2
更新的硬件應(yīng)該使用通用的montgomery模乘算法和ADX codepath。
7.08% nginx [.] sqrx8x_internal 2.30% nginx [.] mulx4x_internal
如果有許多的批量傳輸,如視頻、照片或更通用的文件,需要在分析器的輸出中觀察對(duì)稱(chēng)加密符號(hào)。只需要確保CPU具有AES-NI支持,并為AES-GCM ciphers設(shè)置服務(wù)器端的首選項(xiàng)。根據(jù)perf top信息適當(dāng)?shù)恼{(diào)整硬件。
8.47% nginx [.] aesni_ctr32_ghash_6x
不只是服務(wù)器需要解決加密/解密問(wèn)題,客戶端在缺少可用的CPU時(shí)也會(huì)面臨相同的負(fù)擔(dān)。如果沒(méi)有硬件加速,這可能非常具有挑戰(zhàn)性,因此可以考慮使用一種致力于快速而沒(méi)有硬件加速的算法,例如chacha20-poly1305。這將減少一些移動(dòng)客戶的TTLB。
BoringSSL是支持chacha20-poly1305的,而對(duì)于OpenSSL 1.0.2,可以考慮使用Cloudflare補(bǔ)丁。BoringSSL還支持“相等的首選密碼組”,因此可以使用以下配置,讓客戶端根據(jù)其硬件功能來(lái)決定使用什么密碼(從cloudflare/sslconfig中竊取)。
ssl_ciphers '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES'; ssl_prefer_server_ciphers on;
為了分析高標(biāo)準(zhǔn)的優(yōu)化效果,需要收集RUM數(shù)據(jù)。在瀏覽器中,可以使用導(dǎo)航定時(shí)api和資源定時(shí)api收集。收集的主要指標(biāo)是TTFB和TTV/TTI。擁有便于查詢(xún)和圖形化格式的數(shù)據(jù)將極大地簡(jiǎn)化迭代。
nginx的壓縮從mime.types文件開(kāi)始,它定義了文件擴(kuò)展和響應(yīng)MIME類(lèi)型之間的默認(rèn)通信。然后需要定義傳遞給壓縮器的類(lèi)型。如果想要完整的列表,可以使用mime-db來(lái)自動(dòng)生成mime.types并添加.compressible==true到gzip_types。
在啟用gzip時(shí),兩個(gè)方面要注意。
附注,http壓縮不僅限于gzip,nginx有第三方ngx_brotli模塊,與gzip相比改善后的壓縮率高達(dá)30%。
至于壓縮設(shè)置本身,討論兩個(gè)單獨(dú)的用例:靜態(tài)和動(dòng)態(tài)數(shù)據(jù)。
在代理中緩存會(huì)極大地影響web服務(wù)器性能,特別是在延遲方面。nginx代理模塊有不同的緩沖開(kāi)關(guān),它們?cè)诿總€(gè)位置上都是可轉(zhuǎn)換的。可以通過(guò)proxy_request_buffering和proxy_buffering對(duì)兩個(gè)方向的緩沖進(jìn)行單獨(dú)控制。如果緩沖是啟用了內(nèi)存消耗上限的話,則由client_body_buffer_size和proxy_buffer設(shè)置,達(dá)到請(qǐng)求/響應(yīng)的臨界值后,將緩沖到磁盤(pán)。對(duì)于響應(yīng)的臨界值,可以通過(guò)將proxy_max_temp_file_size設(shè)置為0來(lái)禁用。
常見(jiàn)的緩沖方法有:
無(wú)論你選擇哪種方法,都不要忘記測(cè)試它對(duì)TTFB和TTLB的影響。另外,正如前面提到的,緩沖可以影響IO的使用,甚至是后端使用率,因此也要密切關(guān)注它。
現(xiàn)在我們將討論TLS的高級(jí)方面和延遲改進(jìn),可以通過(guò)正確配置nginx來(lái)實(shí)現(xiàn)。文章提到的大多數(shù)優(yōu)化都包含在高性能瀏覽器網(wǎng)絡(luò)的“優(yōu)化TLS”部分,并在nginx.conf 2014上讓HTTPS更快的討論。此部分中提到的調(diào)優(yōu)將會(huì)影響web服務(wù)器的性能和安全性,如果不確定,請(qǐng)參考Mozilla服務(wù)器端TLS指南和/或與安全團(tuán)隊(duì)協(xié)商。
如何驗(yàn)證優(yōu)化結(jié)果。
像DBA常說(shuō)的那樣,“快的查詢(xún)是從來(lái)沒(méi)有做過(guò)的。”TLS同樣如此,如果你緩存了握手的結(jié)果,可以減少一個(gè)RTT的延遲。有兩種方法緩存握手結(jié)果。
附注一點(diǎn),如果使用session ticket方法,那么值得使用3個(gè)鍵而不是一個(gè)鍵值,例如:
ssl_session_tickets on;
ssl_session_timeout 1h;
ssl_session_ticket_key /run/nginx-ephemeral/nginx_session_ticket_curr;
ssl_session_ticket_key /run/nginx-ephemeral/nginx_session_ticket_prev;
ssl_session_ticket_key /run/nginx-ephemeral/nginx_session_ticket_next;
即便始終使用當(dāng)前的密鑰進(jìn)行會(huì)話加密,也會(huì)接受使用之前和之后密鑰加密的會(huì)話。
需要對(duì)OCSP響應(yīng)作staple,否則:
要staple OCSP響應(yīng),可以定期從證書(shū)頒發(fā)機(jī)構(gòu)獲取它,將結(jié)果分發(fā)給web服務(wù)器,并使用ssl_stapling_file指令來(lái)調(diào)用。
ssl_stapling_file /var/cache/nginx/ocsp/www.der;
TLS將數(shù)據(jù)分解成記錄塊,在完全接收到它之前,無(wú)法對(duì)其進(jìn)行驗(yàn)證和解密??梢詮木W(wǎng)絡(luò)堆棧和應(yīng)用程序的角度來(lái)度量這一延遲。
默認(rèn)的nginx使用16k塊,甚至不適合IW10擁塞窗口,因此需要額外的往返。nginx提供了一種通過(guò)ssl_buffer_size指令設(shè)置記錄大小的方法:
靜態(tài)調(diào)優(yōu)的兩個(gè)問(wèn)題。
還有一種替代方法:動(dòng)態(tài)記錄大小調(diào)整。來(lái)自Cloudflare的nginx補(bǔ)丁為動(dòng)態(tài)記錄大小提供了支持。初對(duì)它進(jìn)行配置可能是一種痛苦,但一旦配置完成,它就會(huì)運(yùn)行得很好。
TLS 1.3的功能確實(shí)很不錯(cuò),但是除非有足夠的資源來(lái)解決TLS的問(wèn)題,否則不建議啟用它,因?yàn)橐韵略颉?
Nginx是一個(gè)基于事件循環(huán)的web服務(wù)器,意味著它只能一次只做一件事。盡管它似乎同時(shí)做了所有這些事情,比如在分時(shí)復(fù)用中,所有的nginx都只是在事件之間快速切換,處理一個(gè)接一個(gè)。這一切都有效,因?yàn)樘幚砻總€(gè)事件只需幾微秒。但如果它開(kāi)始花費(fèi)太多時(shí)間,例如,因?yàn)樗枰D(zhuǎn)到旋轉(zhuǎn)盤(pán)上,延遲就會(huì)飆升。
如果注意到nginx在ngx_process_events_and_timer函數(shù)中花費(fèi)了很多時(shí)間,并且分布是雙向的,那么可能會(huì)受到eventloop stalls的影響。
# funclatency '/srv/nginx-bazel/sbin/nginx:ngx_process_events_and_timers' -m msecs : count distribution 0 -> 1 : 3799 |****************************************| 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 409 |**** | 32 -> 63 : 313 |*** | 64 -> 127 : 128 |* |
因?yàn)锳IO和Threadpools是eventloop的主要來(lái)源,特別是在旋轉(zhuǎn)磁盤(pán)上的IO,所以應(yīng)該優(yōu)先查看,還可以通過(guò)運(yùn)行文件記錄來(lái)觀察受它影響的程度。
# fileslower 10 Tracing sync read/writes slower than 10 ms
TIME(s) COMM TID D BYTES LAT(ms) FILENAME 2.642 nginx 69097 R 5242880 12.18 0002121812 4.760 nginx 69754 W 8192 42.08 0002121598 4.760 nginx 69435 W 2852 42.39 0002121845 4.760 nginx 69088 W 2852 41.83 0002121854
為了解決這個(gè)問(wèn)題,nginx支持將IO卸載到一個(gè)threadpool(它也支持AIO,但是Unixes的本地AIO很不友好,所以好避免它),基本的設(shè)置很簡(jiǎn)單。
aio threads;
aio_write on;
對(duì)于更復(fù)雜的情況可以設(shè)置自定義[線程池](http://nginx.org/en/docs/ngx_core_module.html # thread_pool)的預(yù)留磁盤(pán),如果一個(gè)驅(qū)動(dòng)器失效,它不會(huì)影響其他的請(qǐng)求。線程池可以極大地減少處于D狀態(tài)的nginx進(jìn)程的數(shù)量,從而提高延遲和吞吐量。但是它不會(huì)完全消除eventloop,因?yàn)椴⒉皇撬蠭O操作都被卸載。
記錄日志也會(huì)花費(fèi)相當(dāng)多的時(shí)間,因?yàn)樗谧x寫(xiě)磁盤(pán)。可以通過(guò)運(yùn)行ext4slower檢查是否存在日志,并查找access/error日志引用。
# ext4slower 10 TIME COMM PID T BYTES OFF_KB LAT(ms) FILENAME 06:26:03 nginx 69094 W 163070 634126 18.78 access.log 06:26:08 nginx 69094 W 151 126029 37.35 error.log 06:26:13 nginx 69082 W 153168 638728 159.96 access.log
通過(guò)使用access_log指令的緩沖區(qū)參數(shù),在編寫(xiě)它們之前,通過(guò)在內(nèi)存中對(duì)訪問(wèn)日志進(jìn)行欺騙,可以解決這個(gè)問(wèn)題。再使用gzip參數(shù),將日志寫(xiě)入磁盤(pán)之前壓縮日志,從而減少I(mǎi)O壓力。
但是要在日志中完全消除IO檔位,只能通過(guò)syslog編寫(xiě)日志,這樣日志將與nginx事件循環(huán)完全集成。
因?yàn)閛pen(2)調(diào)用本質(zhì)上是阻塞的,而web服務(wù)器通常是打開(kāi)/讀取/關(guān)閉文件,因此緩存打開(kāi)的文件可能是有益的。通過(guò)查看ngx_open_cached_file函數(shù)延遲,可以看到便利所在。
# funclatency /srv/nginx-bazel/sbin/nginx:ngx_open_cached_file -u usecs : count distribution 0 -> 1 : 10219 |****************************************| 2 -> 3 : 21 | | 4 -> 7 : 3 | | 8 -> 15 : 1 | |
如果看到有太多的開(kāi)放調(diào)用,或者有一些花費(fèi)太多時(shí)間的調(diào)用,可以啟用文件緩存。
open_file_cache max=10000;
open_file_cache_min_uses 2;
open_file_cache_errors on;
在啟用open_file_cache之后,可以通過(guò)查看opensnoop來(lái)觀察所有的緩存遺漏,終決定是否需要調(diào)整緩存限制。
# opensnoop -n nginx PID COMM FD ERR PATH 69435 nginx 311 0 /srv/site/assets/serviceworker.js 69086 nginx 158 0 /srv/site/error/404.html ...
本文描述的所有優(yōu)化都是基于本地的Web服務(wù)器。其中一些提高了拓展性和性能。另外一些與小延遲或更快地將字節(jié)傳送給客戶機(jī)是相關(guān)的。但在以往的體驗(yàn)中,大量用戶可見(jiàn)的性能來(lái)自于更高級(jí)的優(yōu)化,這些優(yōu)化會(huì)影響到整個(gè)Dropbox 邊緣網(wǎng)絡(luò)的行為,比如ingress/egress流量工程和智能的內(nèi)部負(fù)載平衡。這些問(wèn)題處于知識(shí)的邊緣,而行業(yè)才剛剛開(kāi)始接近它們。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對(duì)作者和來(lái)源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請(qǐng)及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對(duì)此聲明的最終解釋權(quán)。