引言
io_uring是Linux內(nèi)核在v5.1引入的一套異步IO接口,隨著其迅速發(fā)展,現(xiàn)在的io_uring已經(jīng)遠(yuǎn)遠(yuǎn)超過了純IO的范疇。從Linux v5.3版本開始,io_uring陸續(xù)添加了網(wǎng)絡(luò)編程相關(guān)的API,對用戶提供sendmsg、recvmsg、accept、connect等接口的異步支持,將io_uring的生態(tài)范圍擴(kuò)大到了網(wǎng)絡(luò)領(lǐng)域。
另外從Linux v5.7開始,io_uring對這些異步接口提供FAST POLL機(jī)制,用戶無需再使用像select、event poll等多路復(fù)用機(jī)制來監(jiān)聽文件句柄,只要把讀寫請求直接丟到io_uring的submit queue中并提交,當(dāng)文件句柄不可讀寫時,內(nèi)核會主動添加poll handler,當(dāng)文件句柄可讀寫時主動調(diào)用poll handler再次下發(fā)讀寫請求,從而減少系統(tǒng)調(diào)用次數(shù)提高性能。
上一篇我們初探了 io_uring 用于網(wǎng)絡(luò)的編程模型以及 echo server benchmark 下的性能表現(xiàn),這篇文章我們將基于通用應(yīng)用 nginx 實戰(zhàn)。
Nginx io_uring 代碼優(yōu)化
Nginx是一款輕量級的Web服務(wù)器、反向代理服務(wù)器,由于它的內(nèi)存占用少,啟動極快,高并發(fā)能力強(qiáng),在互聯(lián)網(wǎng)項目中廣泛應(yīng)用。
從架構(gòu)上看,Nginx由一個master和多個worker進(jìn)程組成,多個worker之間不需要加鎖,獨(dú)立處理與client的連接和網(wǎng)絡(luò)請求。worker是一個單線程大循環(huán),這與上一篇“你認(rèn)為 io_uring 只適用于存儲 IO?大錯特錯!”文章中描述的 echo server 模型基本一致。
基于event poll的編程模型
event poll是Nginx在Linux下的默認(rèn)事件模型。
event poll事件模型把listen fd以及新建連接的sock fd都注冊進(jìn)event poll中,當(dāng)這些fd上有數(shù)據(jù)可讀時,等待在epoll_wait()的worker進(jìn)程會被喚醒,調(diào)用相應(yīng)的回調(diào)函數(shù)進(jìn)行處理,這里的recv、writev請求都為同步請求。
基于io_uring的編程模型
前面提到,io_uring的FAST POLL機(jī)制允許數(shù)據(jù)在未ready的情況下就直接下發(fā),不需要再把普通連接的fd注冊進(jìn)event poll。另外這里的讀寫請求通過io_uring異步下發(fā),處理流程大致如下:
事實上,accept()也可以采取FAFST POLL機(jī)制,無需等待listen_fd數(shù)據(jù)可讀就直接下發(fā),以減少系統(tǒng)調(diào)用次數(shù)。但在調(diào)試過程中發(fā)現(xiàn)這樣accept()失敗概率大大增加,而每次失敗的accept()都會帶來一次無效的sock內(nèi)存申請和釋放,這個開銷較大,因此依然采用類似event poll的方式來偵聽listen fd。后續(xù)針對這塊可以做一些優(yōu)化。
測試結(jié)果
測試環(huán)境
測試機(jī)器
CPU: Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz 64邏輯核
server cmdline添加:mitigation=on
nginx配置
user root;http { access_log off; server { access_log off; // 關(guān)閉access log,否則會寫日志,影響測試 location / { return 200; // 不讀本地文件,直接返回200 } }}
benchmark
使用輕量級HTTP性能測試工具wrk進(jìn)行壓測。
測試命令
長連接 wrk -c $connection -t $thread -d 120 $url短連接wrk-c$connection-t$thread-H"Connection:Close"-d120$url
測試結(jié)果
長連接
? connection=1000,thread=200, 測試server上不同worker數(shù)目性能。
worker數(shù)目在8以下時,QPS有20%左右的提升。隨著worker數(shù)目增大,CPU不成為瓶頸,收益逐漸降低。
server單worker,測試client端不同連接數(shù)性能(thread取默認(rèn)數(shù)2)。
可以看到單worker情況下,500個連接以上,QPS有20%以上的提升。從系統(tǒng)調(diào)用數(shù)目上看,io uring的系統(tǒng)調(diào)用數(shù)基本上在event poll的1/10以內(nèi)。
短連接
? connection=1000,thread=200, 測試server上不同worker數(shù)目性能。
短連接場景,io uring相對于event poll非但沒有提升,甚至在某些場景下有5%~10%的性能下降。究其原因,除了io uring框架本身帶來的開銷以外,還可能跟io uring編程模式下請求批量下發(fā)而帶來的延遲有關(guān)。
總結(jié)及下一步工作
從筆者目前的測試來看,io_uring在網(wǎng)絡(luò)編程方面的優(yōu)化更適合長連接場景,在長連接場景下最高有20%多的提升。短連接場景還有待優(yōu)化,主要考慮以下兩方面:
? io uring本身框架開銷的優(yōu)化,當(dāng)然這個優(yōu)化對長連接同樣適用。
? 針對短連接的優(yōu)化,如針對accept()請求,先檢查是否有數(shù)據(jù)可讀,避免無效內(nèi)存申請釋放;多個accept()一起下發(fā)等。
nginx 和 echo server 等優(yōu)化實踐相關(guān)內(nèi)容(包含源代碼),我們都已經(jīng)在 OpenAnolis 社區(qū)高性能存儲 SIG 開源(openanolis.org)。也歡迎大家積極參與討論和貢獻(xiàn),一起探索 io_uring 的高性能之路。
責(zé)任編輯:xj
原文標(biāo)題:面對疾風(fēng)吧!io_uring 優(yōu)化 nginx 實戰(zhàn)演練
文章出處:【微信公眾號:Linuxer】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
Linux
+關(guān)注
關(guān)注
87文章
11342瀏覽量
210156 -
IO接口
+關(guān)注
關(guān)注
0文章
31瀏覽量
13445 -
nginx
+關(guān)注
關(guān)注
0文章
154瀏覽量
12212
原文標(biāo)題:面對疾風(fēng)吧!io_uring 優(yōu)化 nginx 實戰(zhàn)演練
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論