本篇文章是個經驗談,作者想要聊聊是如何將一個 4vCPU 的VM給調整到可以達到每秒處理 1.2M(120萬)個 JSON Reuqest,本篇文章非常的長,所以會分多天來介紹。
整篇文章探討的是各種 turning 的步驟,來聊聊如何從最初每秒 224k(22萬四千) 給調整到每秒 1.2M 的處理能力。
整個過程分成九大步驟,後面同時標示每個過程後的每秒請求能力
1. Application Optimizations (347k)
2. Speculative Execution Migtigations (446k)
3. Syscall Auditing/Blocking (495k)
4. Disabling iptables/netfilter (603k)
5. Perfect Locality (834k)
6. Interrypt Optimizations (1.06M)
7. The Case of the Nosy Neighbor (1.12M)
8. The Battle Against the Spin Lock (1.15M)
9. This Gost to Twelv (1.20M)
作者強調,上述的過程不一定適合你的應用程式,但是透過這些步驟能夠讓你更佳瞭解應用程式的運作行為,同時也有機會發現一些潛在的瓶頸問題。
環境介紹
1. 團隊使用 Techempower 來進行 JSON Serialization 的測試
2. 使用 libreactor(event-driven框架) 來搭建一個簡單的 API Server
3. HTTP 的解析使用 picohttpparser,同時使用 libclo 來處理 JSON 的編碼
4. 硬體環境
- Server: 4 vCPU, c5n.xlarge AWS VM
- Client: 16 vCPU, c5n.4xlarge AWS VM (clinet太弱會變成瓶頸)
- Network: Server/Client 屬於同一個可用區域(AZ)
5. 軟體環境
- 作業系統: Amazon Linux2 (Kernel 4.14)
- Server: 使用 libreactor (使用不同版本,分別是 Round18 以及 Round20)
- Client: 修改 wrk 這個知名的工具並重新命名為 twrk,詳細差異自己看文章內部,主要都跟顯示有關
6. 實驗方式
- 每個測試跑三次,取中間值
- 256 連線,16 threads,同時每個 thread 都會 pin 到一個固定的 CPU
- 每個實驗都有兩秒的暖機時間來建立連線
Ground Zero
第一個要探討的就是什麼最佳化都還沒有使用前,到底當前應用程式可能的瓶頸在哪裏
首先團隊將該應用程式與其他常見的應用程式或是開發框架比較,譬如 Netty, Nginx, Actix, aspcore 等, libreactor 的效能不錯,有中上水準。
接者作者使用火焰圖(Flame Graphs)來 Profile 該伺服器,作者很好心地將文章中所有的火焰圖都調整了一下,讓所有的 user-space 相關的 function call 都轉成藍色,而剩下跟 kernel 相關都維持紅色。
1. 大部分的時間都在 Kernel 處理
2. 主要是花費在收封包與送封包
3. 應用程式本身主要是分兩大部分,解析 HTTP 的封包以及處理請求與回應。
從上述兩點來看,作者認為目前的應用程式寫得算不錯,因為瓶頸很明顯是卡在 Kernel 端
接下來就正式進入到各種 Turning 的章節探討
Application Optimizations
長話短說:
- 作者基於 libreactor Round18 的框架進行修改,並且所有的修改都已經被合併到 Round20 的版本中,而這些修改主要是實作方面的強化以及整個框架的最佳化。
1. 作者首先透過 htop 觀察運行過程,發現 Server 只有使用 2vCPU 而已(系統有 4vCPU),因此這是作者進行的第一個修改,讓 Server 使用了 4vCPU,這個簡單調整就讓效能提升 25%
註: 作者特別強調,不要覺得從 2vCPU 變成 4vCPU 效能就可以變成兩倍,主要是1) 沒有使用的 vCPU 還有很多其他的工作要處理,因此不是完全都送給你應用程式處理。2)基於 hypter-thread vCPU 的架構,環境只有兩個真正的 CPU 而是透過邏輯的方式產生四個抽象的 CPU,所以全用一定會變快,但是基於很多資源還是要競爭與共用,數字不是單純翻倍
2. 作者自己的應用程式本身使用 gcc 建置時有使用 "-o3" 的方式來最佳化處理,然而框架本身卻沒有使用 "-o3" 的方式來弄,因此作者也針對這個部分來處理,讓建制框架時能夠使用 -o3
3. 從實作方面來看,作者觀察到 libreactor 1.0 版本使用的是 read/write 這兩個常見的方式來處理封包的送收,作者將其修改成 recv/send 整個效能就提升了將近 10%。
註: write(針對 FD,更全面廣泛的用法) 與 send(針對 Socket,更針對的用法) 使用上差異不大,但是 write 於底層 Kernel 最終還是會呼叫到 send 來處理,所以基本上可以理解就是在沒有特別參數需求時,可以直接跳過幾個 kernel function 來達到加速的效果。
write kernel 內的走向: sys_write -> vfs_write -> __vfs_write -> sock_write_iter -> sock_sendmsg
send kernel 內的走向: sendto -> sock_sendmsg
4. 作者觀察到火焰圖中有一些 pthread 相關的資料,進而發現 libreactor 會創造一個 thread pool 來處理非同步的 DNS 名稱解析問題。對於一個 HTTP Client 來說,如果今天要發送請求到多個不同的 domain,而每個 domain 都會需要進行一個 blocking 的解析過程,透過這種方式可以減少 DNS 解析造成的 blocking 問題。然而對於 HTTP Server 來說,這個使用情境帶來的效益似乎就稍微低了些,畢竟 Server 只有 Bind Socket 之前可能會需要去解析一次 DNS 而已。
大部分的情境下, thread pool 都是應用程式初期會去創造而接者就不太會管她,但是對於錙銖必較的效能除錯人來說,任何能夠調整的部分都可能是個值得探討的地方。
作者透過修改 Server 端(準確來說是 libreactor 框架內的程式碼)關於 Thread Pool 的一些用法,成長的讓整個效能提升了 2~3%
結論來說,透過上述四個概念來提升的程式碼效能。
1. vCPU 盡量使用: 25%-27%
2. 使用 gcc -O3 來建置框架的程式碼: 5%-10%
3. 使用 march=native 等參數來建置最後的 server 應用程式: 5%-10%
4. 使用 send/recv 而非 write/read: 5%-10%
5. 修改 pthread 的用法: 2%-3%
註: 作者強調每個最佳化的結果並非是單純累積的概念,反而還會有互補的效果。
可能前述的操作實際上也會讓後續的操作達到更好的效果,
譬如如果先跑 vCPU 的調整,效能大概提升 25%,但是如果先執行別的最佳化過程,最後再來調整 vCPU,就可以達到 40% 的效果,主要是 CPU 可以共有效率的去執行程式。
最後,這個部分讓整個處理封包能力從 224k 提升了 55% 到 347k (req/s)。
從火焰圖來看,整個 user-space 的範圍縮小許多,同時 send/recv 的處理也有使得整體的高度下降一點點(大概四格..)
為了避免文章過長,本篇文章就探討第一個最佳化的過程,剩下的就敬請期待後續!
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
同時也有10000部Youtube影片,追蹤數超過62萬的網紅Bryan Wee,也在其Youtube影片中提到,...
「client server架構」的推薦目錄:
- 關於client server架構 在 矽谷牛的耕田筆記 Facebook
- 關於client server架構 在 純靠北工程師 Facebook
- 關於client server架構 在 愛流浪的小風 Facebook
- 關於client server架構 在 Bryan Wee Youtube
- 關於client server架構 在 Travel Thirsty Youtube
- 關於client server架構 在 スキマスイッチ - 「全力少年」Music Video : SUKIMASWITCH / ZENRYOKU SHOUNEN Music Video Youtube
- 關於client server架構 在 主從式架構三層式架構2022-在Facebook/IG/Youtube上的焦點 ... 的評價
client server架構 在 純靠北工程師 Facebook 八卦
#純靠北工程師36t
今天一位台電資深工程師來現場
資深:請問一下,你們怎麼從現場蒐集資料到Pi Server?
我:先從PLC到現場電腦走ODBC到Pi Client,再到台中廠的Pi Server。
資深: ...
我: ?
資深:你有聽懂我的問題嗎?你看過架構圖嗎?你有來開會嗎?
我:抱歉,我沒去開會(我不是PM),也沒看過(但記在腦海中),可以請你指教?
資深:對嘛,你不懂我的問題,也沒來開會,也沒看過架構圖。你今天是來幹嘛的?
接洽工程師:學長,不是啦!他的意思是...(繪畫方塊圖鉅細靡遺解說)
資深:這...這樣講才對嘛
有人可以教我更低階的語言嗎?可以更貼近國營資深工程師溝通的那種
👉 去 GitHub 給我們🌟用行動支持純靠北工程師 https://github.com/init-engineer/init.engineer
📢 匿名發文請至 https://kaobei.engineer/cards/create
🥙 全平台留言 https://kaobei.engineer/cards/show/4133
client server架構 在 愛流浪的小風 Facebook 八卦
上次跟大家分享了縮短 Release 的價值,用實際的數字來讓大家感受一下,透過縮短 Release 週期所帶來的好處,希望大家也可以實際的試試看縮短 Release 週期,不過在談到要縮短 Release 週期的時候,聽到最多的困擾是,那實際上要怎麼做,才能夠讓 Release 這件事情可以快速並且頻繁的發生呢?
1. 適當的 Task 大小
通常在做任務拆分時,我會希望把 Task 大小控制在 1~3 天能完成的範圍(這就看個人,我個人喜歡至少這個粒度,不過越小越好),就算是一個大功能的局部功能也好,並且這個 Task 在做完之後就可以直接上線,是能跟完全相容現在的系統,在透過系統架構設計,例如 Config 或 Feature Flag 來控制功能是否開放給使用者。
(打完這一部分之後就發現有另外兩件事情可以和大家聊聊,關於任務拆分的處理和如何透過系統架構設計來持續上線程式碼 XD)
2. Code review
Code review 其實是團隊協作中很重要的一件事情,當然如果你們經常直接 Pair Programming 的話就可以省去這一段,我很喜歡 Code review 的一個原因,是因為這是一個討論程式碼實現的很好機會,通常你會有一些具體的例子可以來討論,並且也可以同步團隊成員對於整個系統架構的期望,所以除了確認程式碼是否正確之外,不要浪費這個機會和團隊成員們交流討論,這也是一個偷偷學習別人思路的好時機!另外透過 Code review ,還能確保大家對於整個系統的認知是有跟上進度的,像我們目前團隊就會確保至少有接近 50% 的成員 Approve 之後才能 Merge PR,讓大家在不能 Mob 時也能跟上大家所做的變更。
3. 持續整合、部署
除了人為的 Code review 之外,我通常還會相當依賴 CI Server 來幫我們做各種面向的檢查,從最基本的測試我們就有至少單元測試、整合測試、視覺 (Visual) 測試等等,還有團隊開發一定需要的 Linter 來確定程式碼風格一致,如果更進階一點就是可以做安全性掃描或是程式碼分析,如果做的是 Web 或 App 的開發還可以考慮做一些 Benchmark 來確保系統的執行速度符合預期,既然了解了持續快速部署才是產生價值的最大方式,我們就應該讓所有能自動的就自動化,才能讓人力專注在最需要的地方,剩下的就交給自動化工作來處理就好了
4. 監控
在聊持續部署、快速部署的時候,一個很常見的誤區是很多人以為上線後就結束了,我只要盡量的在 Merge 之前確保做好各種事情,然後想辦法讓 Pull Request 變綠燈,拿到足夠的 Approve,然後 Merge 進去我就馬上趕快開始新的工作。
但其實對於使用者來說, Merge 程式碼之後才算是真正的開始,因為他們才能夠開始使用你所部署的新功能,所以持續部署中最重要的事情是 ”上線之後”,有沒有足夠的監控機制可以知道你系統運作的情形,不只是有一些 CloudWatch 的 Monitor 或是 Centralised 的 Log 管理系統來幫助除錯,甚至你應該要建立一些 Client events 的 Tracking 或是 Funnel 來監控你的系統是不是可以被正常使用,如果有任何異常的時候能在客戶回報前就能發現,現在其實有很多的現成工具可以使用,有些還能夠直接設定自動警示,讓你在系統有流程中斷的時候被通知。
5. 異常排除
在有了足夠的監控系統之後,你有沒有足夠的手段來減輕這些異常對於客戶的影響,舉例來說,假如今天你結帳流程中本來有信用卡結帳跟超商付款,如果今天信用卡公司剛好故障,你能不能透過 Feature Toggle 或是 Config 來暫時關閉信用卡功能,讓使用者還是可以使用其他的方式結帳,這件事情你可以多快完成,它是否需要重新部署才能做到,都會是異常排除一個很重要的指標,當然今天這個例子是客戶端的異常排除,如果今天是 Cloud Service 發生問題時的異常排除也是一個很經點的例子,至少也要有跨 Region 的 BCP。
6. 成效追蹤
功能上線之後,你是否能夠知道這個功能對於客戶帶來多大的改善,對於系統有多少的優化,其實都是需要被 ”量化” 追蹤的,很多人都會誤以為用感覺來測量就足夠了,沒有實際的量化其實很難評估回顧一個新功能的規劃是否產生了正確的價值,還是其實一切都是感覺良好,例如你更新的購物流程的畫面,是否實際對整個流程的轉換率有所提升,還是只是單純的變好看但對業績沒有幫助,這些其實都是需要很赤裸的被量測,才能真正的作為疊代的依據,找出團隊目前的方向和規劃方式有沒有問題。
我覺得在敏捷開發中很容易被誤解的是,很多人以為只要用了對了方式(或是大家都在用的方式),就可以讓產品快速開發、上線並疊代,跟上那些新創獨角獸的腳步,卻忽略了這些其實都是軟體的技術基礎硬實力,通常大家只會跟你說他們使用某種方法帶來很多成效,但不會透露背後做了多少的基礎改善,所以要小心就算所有團隊成員心態正確,老闆觀念正確,沒有相對應的硬實力,敏捷也只是空談,當然,如果你想要改善軟體開發硬實力也不是不可能,我推薦最簡單直接的方式就是找 91 敏捷開發之路
你在做持續 Release 的時候也有遇到什麼樣心得或痛點嗎?歡迎你也分享一下你對這件事情的看法喔!粉絲團默默的快 1000 人了,我也開始打算來個每週固定更新,如果你覺得我的分享不錯的話,歡迎你也對我的粉絲團按讚喔!
client server架構 在 スキマスイッチ - 「全力少年」Music Video : SUKIMASWITCH / ZENRYOKU SHOUNEN Music Video Youtube 的評價

client server架構 在 主從式架構三層式架構2022-在Facebook/IG/Youtube上的焦點 ... 的八卦
主從式架構(英語:Client-server model) 也稱客戶端/伺服器架構、C/S架構,是一種網路架構,它把客戶端(Client,通常是一個採用圖形化使用者介面的程式)與伺服 . ... <看更多>