如何預熱Spring Boot應用? - sebstein
Spring Boot 是用於開發 Java 和 Kotlin 後端的成熟工具。如果您重新啟動這樣的後端,第一個 REST 呼叫總是需要很長時間。我研究了為什麼會這樣,以及如何在應用程式啟動時對其進行預熱,以便快速處理第一個請求。
在Spring Boot 應用程式啟動期間,JVM載入各種類。通過第一個REST 請求,JVM 再次載入許多類,但不會通過對 REST 端點的任何進一步呼叫載入更多類。
Spring Boot 中的第一個請求很慢,那麼為什麼第一個請求必須快?API 有約定的響應時間,此外,應用程式每週更新幾次,有多個例項,這導致每週有大量的“第一次請求”。
我現在應該如何預熱應用程式?第一個天真的想法是在啟動時簡單地呼叫 REST API 的所有端點,以便載入所有類。
實際上,這很困難。
解決方案:特殊端點來預熱 Spring Boot:
在我的實驗中,我注意到只有對任何端點的第一個請求很慢。對另一個端點的下一個請求要快得多。基於這個觀察,我萌生了寫一個特殊的REST端點,只用於熱身的想法。
這個特殊端點就是:在端點中使用一個 DTO,能包含經常使用的資料型別如String、BigInteger 等,還包括經常使用的用於驗證的註釋:
例如,下面是使用WarmUpController加上相關的請求和響應 DTO:
public class WarmUpRequestDto { @NotBlank @Pattern(regexp = "warm me up") private String warmUpString; @Min(10) @Max(20) private int warmUpNumber; @Valid private WarmUpEnumDto warmUpEnumDto; @NotNull private BigDecimal warmUpBigDecimal; ... } |
WarmUpRequestDto 中,有在普通端點中使用的所有資料型別,並且還使用了一個Enum 類。所有屬性都進行了註釋以進行驗證。
如何自動啟用這個Rest端點?
在等待ApplicationReadyEvent的PreloadComponent中實現了一個事件偵聽器。ApplicationReadyEvent 是當應用程式從 Spring 的角度完全啟動時由 Spring 生成的。在函式sendWarmUpRestRequest () 中,我使用Spring WebClient向我的WarmUpController傳送一個 REST 請求。
private void sendWarmUpRestRequest() { final String serverPort = environment.getProperty("local.server.port"); final String baseUrl = "http://localhost:" + serverPort; final String warmUpEndpoint = baseUrl + "/warmup"; logger.info("Sending REST request to force initialization of Jackson..."); final String response = webClientBuilder.build().post() .uri(warmUpEndpoint) .header(CONTENT_TYPE, APPLICATION_JSON_VALUE) .body(Mono.just(createSampleMessage()), WarmUpRequestDto.class) .retrieve() .bodyToMono(String.class) .timeout(Duration.ofSeconds(5)) .block(); logger.info("...done, response received: " + response); } |
在GitHub 上的示例程式碼中,我註釋掉了對onApplicationEvent(ApplicationReadyEvent 事件)函式的呼叫。
有興趣的讀者如果想看懂,必須去掉這個註釋,重新編譯啟動應用程式:
mvn package ... java -verbose:class -jar target/warm-me-up*.jar |
幾秒鐘後,我的終端平靜下來,我再次刪除了內容。現在我使用 curl 再次執行第一個請求。第一次呼叫只用了 37 毫秒,而不是未優化的 200 毫秒。
Spring Boot 中還需要預熱什麼?
我的示例應用程式現在已充分預熱。當然,在現實中,事情更復雜,需要做更多的工作。還必須預熱以下元件,以便儘快處理第一個請求:
- 建立資料庫連線並進行查詢
- 建立與 Kafka 等訊息代理的連線
- 例項化其他解析庫,例如用於 XML 處理的 JAXB
- 載入本機 C 庫
修復這些問題中的任何一個都可能需要幾天的工作。但是很好,多虧了 JVM 選項:
-verbose:class |
這個引數可以檢視 JVM 何時載入了哪些類!
相關文章
- Spring boot應用如何支援httpsSpring BootHTTP
- 如何優雅地停止 Spring Boot 應用?Spring Boot
- Spring Boot 和 Spring Cloud 應用記憶體如何管理?Spring BootCloud記憶體
- Spring Boot中如何使用Ostara監控應用?Spring Boot
- Spring Boot 之路(一):一個簡單的Spring Boot應用Spring Boot
- spring-boot-route(十八)spring-boot-adtuator監控應用Springboot
- Spring Boot應用監控實戰Spring Boot
- Spring Boot應用程式有哪些功能?Spring Boot
- Spring Boot 應用程式中的 QueryDSLSpring Boot
- Spring Boot + Kotlin + Coroutines應用演示程式Spring BootKotlin
- Spring Boot應用程式事件教程 - reflectoringSpring Boot事件
- Spring Boot整合熱部署框架Spring Boot熱部署框架
- 用Spring Boot顛覆Java應用開發Spring BootJava
- 如何在Spring Boot應用程式中啟用GZIP壓縮? | 前端後端Spring Boot前端後端
- Spring Boot Admin2.1應用監控Spring Boot
- Spring Boot 應用程式啟動流程分析Spring Boot
- 在Spring Boot應用啟動時如何執行程式碼? -DukesletterSpring Boot行程
- 你知道如何自動儲存 Spring Boot 應用程式號嗎Spring Boot
- spring-boot-plus1.1.0.釋出-整合Spring Boot Admin管理和監控應用Spring Boot
- 快速啟動:基於CRaC實現Spring Boot 3恢復預熱Spring Boot
- 如何使用ParcelJS在Spring Boot應用程式中打包前端 - codecentric AG BlogJSSpring Boot前端
- 如何將Spring Boot應用中日誌輸出格式改為JSON?-DEVSpring BootJSONdev
- 在Spring Boot應用程式中使用Kubernetes ConfigMapSpring Boot
- 使用Prometheus和Grafana監控Spring Boot應用PrometheusGrafanaSpring Boot
- Spring Boot + MongoDB 應用的 Docker 化實踐Spring BootMongoDBDocker
- Spring Boot 如何熱載入jar實現動態外掛?Spring BootJAR
- Spring Boot 如何熱載入 jar 實現動態外掛?Spring BootJAR
- 8.Spring Boot 打包與熱部署Spring Boot熱部署
- Spring Boot(十二):Spring Boot 如何測試打包部署Spring Boot
- Spring Boot 響應jspSpring BootJS
- Spring Boot 單體應用一鍵升級成 Spring Cloud AlibabaSpring BootCloud
- 使用Spring Security 6.1及更高版本保護Spring Boot 3應用Spring Boot
- [譯] 用 Apache Shiro 來保護一個 Spring Boot 應用ApacheSpring Boot
- Spring Boot應用中進行任務排程Spring Boot
- 最佳化Spring Boot應用的Docker打包速度Spring BootDocker
- 使用混沌候攻擊測試Spring Boot應用Spring Boot
- Spring Boot應用程式中的常用註釋列表Spring Boot
- Spring Boot Serverless 實戰系列“部署篇” | Mall 應用Spring BootServer