當前位置:
首頁 > 知識 > 用 Python 實現每秒處理 120 萬次 HTTP 請求

用 Python 實現每秒處理 120 萬次 HTTP 請求

來源:碼農網


鏈接:www.codeceo.com/article/python-120m-http-request.html

用 Python 實現每秒處理 120 萬次 HTTP 請求



用 Python 做到每秒處理上百萬次 HTTP 請求,可能嗎?也許不能,但直到最近,這已成為現實。

很多公司都在為了提升程序的執行性能和降低伺服器的運營成本,而放棄 Python 去選擇其它編程語言,其實這樣做並不是必須,因為 Python 完全可以勝任這些任務。


Python 社區最近做了大量關於性能的優化。CPython 3.6 重寫了新的字典從而全面提升解析器的執行性能。由於引入更快的調用規則和字典查詢緩存,CPython 3.7 甚至還要更快。


我們可以用 PyPy 的 Just-in-Time 來編譯複雜的科學計算任務,NumPy 的測試套件也優化了和 C 擴展的兼容性,同時 PyPy 還計劃於今年晚些時候做到和 Python 3.5 保持一致。


這些振奮人心的變化激勵著我想要有所創新,Python 所擅長的領域眾多,我選擇了其中一個:Web 和 MicroServices 開發。


了解 Japronto!


Japronto 是一個全新的,為微服務量身打造的微框架。實現它的主要目標包含夠快、可擴展和輕量化。的確它快的嚇人,甚至遠比 NodeJS 和 Go 還要快的多的多。要感謝 asyncio,讓我可以同時編寫同步和非同步代碼。

用 Python 實現每秒處理 120 萬次 HTTP 請求



Python 的微框架(藍色)、NodeJS 和 Go (綠色) 和 Japronto (紫色)


勘誤表:用戶 @heppu 提到,如果謹慎點用 Go 的 stdlib HTTP 伺服器可以寫出比上圖的 Go 快 12% 的代碼。另外 fasthttp 也是一個非常棒的 Go 伺服器,同樣的測試中它的性能幾乎只比 Japronto 低 18%。真是太棒了!

更多細節查可以看 :


https://github.com/squeakypl/japronto/pull/12 和 https://github.com/squeaky-pl/japronto/pull/14

用 Python 實現每秒處理 120 萬次 HTTP 請求



我們可以看到其實 Meinheld WSGI 伺服器已經和 NodeJS 和 Go 的性能差不多了。儘管它用的是阻塞式設計,但還是要比前面那四個要快的多,前面四個用的是非同步的 Python 解決方案。所以,不要輕易相信別人那些關於非同步系統總是比同步系統更快的說法,雖然都是並發處理的問題,但事實遠不如想像的那麼簡單。


雖然我只是用 「Hello World」 來完成上面這個關於微框架的測試,但它清晰的展現了各種伺服器框架的處理能力。


公平起見,所有程序,包括 Go,都只運行在單個處理器內核上。測試工具為 wrk,參數是 1 個線程,100 個鏈接和每個鏈接 24 個請求(累計並發 2400 次請求)。

用 Python 實現每秒處理 120 萬次 HTTP 請求



HTTP 流水線(圖片來自 Wikipedia)

HTTP 流水線在這裡起著決定性的因素,因為 Japronto 用它來做執行並發請求的優化。


大多數伺服器把來自客戶端的流水線和非流水線請求都一視同仁,用同樣的方法處理,並沒有做針對性的優化。(實際上 Sanic 和 Meinheld 也是默默的把流水線請求當做非流水線來處理,這違反了 HTTP 1.1 協議)


簡單來說,通過流水線技術,客戶端不用等到伺服器端返回,就可以在同一條 TCP 鏈接上繼續發送後續的請求。為了保障通訊的完整性,伺服器端會按照請求的順序逐個把結果返回給客戶端。


細節優化過程


當一堆小的 GET 請求被客戶端以流水線打包發送過來,伺服器端很可能只需要一次系統調用,讀取一個 TCP 數據包就能拿到全部的請求。


系統調用,以及在內核空間到用戶空間之間移動數據,相比起在進程內部移動數據,成本要高的多。這就是為什麼不到萬不得已,要儘可能少做系統調用的次數。


當 Japronto 收到數據並成功解析出請求序列時,它會嘗試儘可能快的把這些請求執行完成,並以正確的順序合并所有結果,然後只執行一次系統調用發送數據給客戶端。


實際上,因為有 scatter/gather IO 這樣的系統調用,合并的工作並不需要自己去完成,只不過 Japronto 暫時還沒有用到這些功能。


然而事情並不總是那麼完美,有時候請求需要耗費很長時間去處理,等待完成的過程增加了不必要的延遲。


當我們做優化時,有必要考慮系統調用的成本和請求的預期完成時間。

用 Python 實現每秒處理 120 萬次 HTTP 請求



經過優化 Japronto 拿到了 1,214,440 RPS 的成績。


除了利用客戶端流水線請求,和優化調用,還有一些其它可用的技術。


Japronto 幾乎都是用 C 寫的。包含解析器、協議、鏈接管理、路由、請求、應答等對象都是用 C 擴展寫的。


Japronto 力圖做到 Python 的懶載入,比如,協議頭的字典只有在被試圖請求到時才會被創建,另外一系列的對象也只有在第一次使用時才會被創建。


Japronto 使用超牛逼的 picohttpparser C 庫來解析狀態、協議頭以及分片的 HTTP 消息體。Picohttpparser 是直接調用現代 CPU 集成的 SSE4.2 擴展文本處理指令去快速匹配 HTTP 標記的邊界(那些 10 年前的老 x86_64 CPU 都有這玩意兒)。I/O 用到了超棒的 uvloop,它是一個 libuv 的封裝,在最底層,它是調用 epoll 來提供非同步讀寫通知。

用 Python 實現每秒處理 120 萬次 HTTP 請求



Picohttpparser 依賴 SSE4.2 和 CMPESTRI x86_64 的特性做解析

Python 是有垃圾收集功能的語言,為避免不必要的增加垃圾收集器的壓力,在設計高性能系統時一定要多加註意。Japronto 的內部被設計的嘗試避免循環引用和儘可能少的分配、釋放內存,它會預先申請一塊區域來存放對象各種,同時嘗試在後續請求中重用那些沒有被繼續引用的 Python 的對象,而不是將那些對象直接扔掉。


這些預先申請的內存的大小被固定為 4KB 的倍數。內部結構會非常小心和頻繁的使用這些連續的內存區域,以減少緩存失效的可能性。


Japronto 會儘可能避免不必要的緩存間複製,只在正確的位置執行操作。比如,在處理路由時,先做 URL 解碼再進行路由匹配。


開源貢獻者們,我需要你們的幫助


我已經連續不斷的開發 Japronto 超過三個月,不光在每一個工作日,周末也無休。除了每天的工作外,我把所有時間精力都投入到這個項目上了。


我想是時候和社區分享我的勞動果實了。


Japronto 已經可靠的實現了下面這些功能:


實現 HTTP 1.x 並且支持分片上傳


完整支持 HTTP 流水線


可配置是否讓鏈接 Keep-alive

支持同步和非同步視圖


Master-multiworker 多任務處理


代碼熱載入


簡單易用的路由規則


下一次,我將深入研究關於 Websockets 和 HTTP 非同步應答數據流。


寫文檔和做測試還有許多工作要做,如果你有興趣加入我,請在 Twitter 上直接聯繫我. 這裡是 Japronto 的 GitHub 項目倉庫。


同時,如果你的公司正在尋找熟悉性能優化和 DevOps 的 Python 工程師,我很樂意為你效勞,在全球任何地方都可以。


結束語


上面提到的所有技術不只適用於 Python,也同樣可以被應用到其它語言,如 Ruby、JavaScript,甚至 PHP 等。我非常感興趣去付諸實踐,但是,除非有人能在這事上投入資金支持,恐怕我沒有足夠的精力去完成。


在此我要感謝 Python 社區為優化性能所付出的持續投入。尤其是 Victor Stinner @VictorStinner、INADA Naoki @methane 和 Yury Selivanov @1st1 以及整個 PyPy 團隊。

獻給我摯愛的 Python。


在微信公眾號內回複數字「1」


小編拉你進粉絲微信群


不是在文章評論里回復


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

用 Python 分析四年NBA比賽數據,實力最強的球隊浮出水面
Python 面試問答 Top 25
Python函數里的愛情故事
用Python分析周杰倫6.5W字的歌詞,原來他是這樣的人
為什麼有那麼多人選擇Python,真的有那麼好嗎?

TAG:Python |

您可能感興趣

ThinkPad E485/E585搭載Ryzen處理器
第二款Intel 10nm處理器現身:1.5GHz 8代Core M3
TYAN於Computex2018展示支持AMD EPYC處理器伺服器
Apple Pencil+A10處理器,2018款iPad發布僅售2588元
Intel正式公布首顆10nm處理器i3-8121U:支持LPDDR4
蘋果發布新款iPad 配A10處理器 蘋果筆 Touch ID 2588元起
都是A11處理器,憑啥iPhoneX比iPhone8P貴3000,對比後明白了!
TDP功耗僅86W!intel 發布18核神U:XEON D-2100處理器
2018款iPad全解析:換裝A10處理器 支持Apple Pencil
Intel發布第8代處理器:2018款MacBook Pro有望使用!
HTC將發Desire 12 Plus 搭載高通450處理器
AMD Ryzen 7 2700X與AMD Ryzen 5 2600X首測,全面壓制Intel第八代處理器?
OPPO R15/R15夢鏡版完整泄漏,處理器採用Helio P60與驍龍660
AMD Ryzen 7 2700X處理器再曝
如何將Python自然語言處理速度提升100倍:用spaCy/Cython加速NLP
Apple iPad 2018升級,支持Apple Pencil,A10處理器
聯想推ThinkPad E485/E585商務本:搭載AMD處理器
TDP 12W!驍龍1000處理器要硬剛intel
BlackBerry KEY2泄露 搭載高通處理器660
Intel推出Core i3-8130U處理器