我有一個 Spring Boot 應用程式,它有時必須通過 REST API 提供非常大的 JSON 有效負載(幾 MB),這需要相當長的時間來下載。
資料從資料庫中讀取,序列化為 JSON 并發送回客戶端。資料庫讀取操作很快,即使對于大資料集,通常也低于 1 秒。所以我的結論是,最耗時的部分是 HTTP 交換。
我已經為 HTTP 交換啟用了 GZIP 壓縮,因此在發送之前應該壓縮有效負載。看起來這很有效(回傳的有效負載確實被壓縮了),但是,沒有明顯的性能提升。
對curl應用程式端點的未壓縮請求需要 49 秒,并產生約 10 MB 的 JSON 有效負載:
curl -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Basic <REDACTED>" --data-binary @priorities-request.json 'https://<REDACTED>/api/rest/priorities' > priorities-response.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 10.0M 0 9.9M 100 85081 205k 1715 0:00:49 0:00:49 --:--:-- 239k
啟用 GZIP 壓縮后,相同的請求需要 42 秒并產生約 260 kb 的 GZip 壓縮 JSON 負載:
curl -H "Content-Type: application/json" -H "Accept: application/json" -H "Accept-Encoding: gzip,deflate,br" -H "Authorization: Basic <REDACTED>" --data-binary @priorities-request.json 'https://<REDACTED>/api/rest/priorities' > priorities-response.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 259k 0 176k 100 85081 4221 1991 0:00:42 0:00:42 --:--:-- 14408
我的預期是,下載壓縮的 260K 有效負載將比未壓縮的 10 MB 下載花費的時間少得多。
我的錯誤是什么?
編輯:因為在評論中有人問我如何設定 GZIP 壓縮:我在Tomcat中設定compression="on"和。而已。其余的由 Tomcat 的 org.apache.coyote.http11.filters.GzipOutputFilter 類完成。compressableMimeType="application/json"server.xml
編輯 2:為了排除將資料序列化為 JSON 是浪費時間的原因,我在本地使用 Jackson2JsonMessageConverter 進行了測驗,但將一個巨大的資料結構寫入 10MB JSON 字串也只需要大約 0.5 秒。
編輯 3:我發現最令人費解的是,使用 API 的客戶端應用程式在同一物理機器上的另一個 Tomcat 實體上運行,在檢索資料時仍然會遇到相同的延遲。
uj5u.com熱心網友回復:
使用 gzip 時,需要考慮 CPU 使用率和帶寬使用率之間的權衡。最終用戶的優勢(更少的傳輸時間,即更快的下載速度)將需要服務器端的額外 CPU 周期。
如果您運行負載測驗,性能提升肯定是可見的。此外,如果您的 API 被應用程式中的其他 API 在內部使用,它將大大減少網路使用量。CPU 使用率可能不是那么重要。
uj5u.com熱心網友回復:
如果您計劃通過網路發送壓縮資料,則可能不是在從 DB 讀取資料時而是在將其寫入 DB 時進行壓縮。這樣壓縮時間就不會成為請求的一部分,并且可以節省存盤空間。比禁用 HTTP compressin 并從 DB 讀取壓縮的二進制資料并將其發送過來
uj5u.com熱心網友回復:
我們想通了:原來 HTTP 交換與它沒有任何關系。
瓶頸實際上是資料庫,但我們一開始并沒有注意到,因為 JPA 查詢幾乎立即回傳。
我們沒有看到的是,檢索到的物件中的許多屬性都是“延遲”加載的,因此只有在 JSON 序列化程式訪問這些屬性時才會執行對它們的 DB 查詢。這些查詢沒有使用 Tomcat 機器上的任何 CPU 時間,因此我們無法通過分析檢測到時間損失。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/515237.html
下一篇:工廠方法“dataSource”拋出例外;嵌套例外是java.lang.NumberFormatException:無法決議空字串
