通過移除Nginx,我們如何將TPS提高了44%?
在 Raygun ,追求極致性能已然成為公司文化的一部分。在發布本文時,我們在 Twitter 上被問到一個問題,為什么我們會使用 Nginx 作為 Raygun API 應用程序的代理。
回答是,這是微軟推薦的方法。事實證明,自.NET Core 2.1 發布以來,情況并非如此。從我們第一次使用.NET Core 1.0 到現在,Kestrel 已經成熟很多,并且自.NET Core 2.1 發行以來,微軟的安全專家們對 Kestrel 在前端服務的表現感到十分滿意。
1. 為什么移除或使用 Nginx?
在某些情況下,大家仍然會堅持使用 Nginx 這樣的代理,我會在下面給你列舉出來。對于 Raygun,我們的 API 服務器僅托管了一個應用程序,然后僅通過負載均衡設備公開到互聯網。這意味著對端口共享的限制并不適用于我們,開放給外部的服務已經被最小化了。
我們可能要使用代理的一些原因(來自微軟的一篇博文),列舉如下:
- 限制其托管應用程序的對外公開部分
- 提供附加的配置和防御層
- 方便與現有基礎架構更好地集成
- 簡化負載平衡和安全通信(HTTPS)配置。只有反向代理服務器需要 X.509 證書,并且該服務器可以使用 HTTP 與內部網絡上的應用服務器進行通信。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1#when-to-use-kestrel-with-a-reverse-proxy
2. 移除 Nginx 后的業務表現
對于我們的 API 節點,從配置中刪除 Nginx 可以使我們處理更多的請求而無需額外費用。
通過負載測試,我們還發現請求的平均響應時間和第 99 百分位響應時間得到顯著改善。這意味著我們的客戶對 API 服務的請求更快,并允許他們在單位時間內發送更多數據。
自從將新的服務器配置投入生產以來,我們的負載均衡設備報告 5xx 錯誤也大大減少了。現在,我們可以支撐處理更高的客戶端負載,而且用戶遇到的錯誤問題也更少了。
3. 我們如何測試.NET Core 性能
我們在亞馬遜的 AWS c5.large 實例 Ubuntu 18.04 環境下進行了測試。基準服務器運行了 Nginx 和 Kestrel Web 服務,Nginx 作為 Kestrel Web 服務代理;作為對比,在另一臺服務器上,服務請求直接由 Kestrel 處理。
我們使用 Apache JMeter 將 Raygun Crash Reporting 樣本有效負載發布到服務 API。JMeter 可以模擬非常高的并發請求負載。我們對此不斷進行調整,讓每臺服務器都最大程度地利用 CPU,逼近服務過載即將不能支撐處理所有請求的極限(但是仍然保證請求的成功率為 100%)。
https://raygun.com/platform/crash-reporting
使用 JMeter 運行多次測試,每個測試持續 10 分鐘,每次測試結束時生成保存測試摘要報告。
最后,我們將多次測試的結果取平均值,最終得出下面的測試結果。
4. 移除 Nginx 后的結果展示
響應時間(毫秒)
平均響應時間(該值越小性能越好)從 1.2ms 減少到 0.8ms,相當于降低了 33%;第 99 百分位響應時間從 6ms 減少到 4ms,相當于降低了 33%。
TPS
TPS(該值越大性能越好)從 3783 個增加到 5461 個,相當于提升了 44%。
5. 在生產環境運行新配置服務的觀察結果
內存使用情況
使用 Nginx 運行該服務實例時,每個實例使用的平均內存非常一致,內存使用率在 13%和 16%之間。
自從刪除 Nginx 以來,我們已經看到服務進程的內存使用率變大,在 15%到 30%之間,平均值趨近為 22%。我們確信這是由于 Nginx 限制了 Kestrel 處理的請求數量。
因此,Kestrel 在高并發下始終會以一定的速率處理請求,這意味著內存使用量幾乎沒有很大變化。消除這一瓶頸后,由于 Kestrel 會處理數量不等的請求,我們現在可以看到更多的內存使用和變化情況。
Nginx + Kestrel
Kestral only
平均活躍節點數
活躍節點的平均數量從 5.35 下降到 4.66。現在,我們可以看到相當長的時間內僅僅運行著四個服務器;而在同一時段的高峰時期,相比之前使用 Nginx,我們同樣運行著更少的服務器。
Nginx + Kestrel
Kestral only
負載均衡設備的 5xx 錯誤率
一段時間以來,我們發現通過負載均衡設備統計的信息報告中,5xx 錯誤率很高,如下圖所示。這些錯誤并不是來自我們應用程序,而且在 Raygun 也沒有對其認定為故障并進行報告。
原來,這些錯誤來自 Nginx,并且通過刪除此代理,我們現在可以更好地處理滿負載,而且大大減少了故障的發生。
總體而言,由于我們服務器處理的請求量很大,即使是以下較高的數量也僅占我們處理的總請求量的很小一部分。注意到通過刪除 Nginx 層可以得到顯著的性能提升,這一點是值得肯定的。我們并不是對 Nginx 進行批評和否定,當然也有可能是我們 Nginx 最終的配置問題,但是,簡化配置似乎可以更好地解決這個問題。
6. 總結
敢質疑關于性能問題的原始假設非常棒,在 Raygun,我們追根溯源,最終發現問題以及解決了問題。隨著我們基礎架構的不斷拓展,能夠以更低成本處理更多的數據,這給我們帶來了一些可觀的業務收益,而這一切都始于有人問了一個簡單的問題:“為什么?”
值得注意的是,.NET 團隊一直在努力改善和優化性能。盡管.NET 5 計劃于今年 11 月發布,但目前已經有很多重要更新可以使用了。