Spring 框架給企業軟件開發者提供了常見問題的通用解決方案,包括那些在將來開發中沒有意識到的問題。可是,它構建的 J2EE 項目變得愈來愈臃腫,逐漸被 Spring Boot 所替代。Spring Boot 讓咱們建立和運行項目變得更爲迅速,如今已經有愈來愈多的人使用它。咱們已經在幾個項目中使用了 Spring Boot ,今天咱們就來一塊兒討論一下如何改進 Spring Boot 應用的性能。html
首先,從以前我在開發中遇到的一個問題提及。在一次查看項目運行日誌的時候,我偶然發現了一個問題,日誌裏顯示這個項目老是加載 Velocity 模板引擎,但實際上這個項目是一個沒有 web 頁面的 REST Service 項目。因而我花了一點時間去尋找產生這個問題的緣由,以及如何改進 Spring Boot 應用的性能。在查找了相關的資料後,我得出的結論以下:java
默認狀況下,咱們會使用 @SpringBootApplication 註解來自動獲取的應用的配置信息,但這樣也會給應用帶來一些反作用。使用這個註解後,會觸發自動配置( auto-configuration )和 組件掃描 ( component scanning ),這跟使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三個註解的做用是同樣的。這樣作給開發帶來方便的同時,也會有兩方面的影響:git
一、會致使項目啓動時間變長。當啓動一個大的應用程序,或將作大量的集成測試啓動應用程序時,影響會特別明顯。github
二、會加載一些不須要的多餘的實例(beans)。web
三、會增長 CPU 消耗。spring
針對以上兩個狀況,咱們能夠移除 @SpringBootApplication 和 @ComponentScan 兩個註解來禁用組件自動掃描,而後在咱們須要的 bean 上進行顯式配置:api
// 移除 @SpringBootApplication and @ComponentScan, 用 @EnableAutoConfiguration 來替代 @Configuration @EnableAutoConfiguration public class SampleWebUiApplication { // ... // 用 @Bean 註解明確顯式配置,以便被 Spring 掃描到 @Bean public MessageController messageController(MessageRepository messageRepository) { return new MessageController(messageRepository); }
咱們在上面提到,@SpringBootApplication 註解的做用跟 @EnableAutoConfiguration 註解的做用是至關的,那就意味着它也能帶來上述的三個問題。要避免這些問題,咱們就要知道咱們須要的組件列表是哪些,能夠用 -Ddebug 的方式來幫助咱們明確地定位:tomcat
mvn spring-boot:run -Ddebug … ========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DispatcherServletAutoConfiguration - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) ...
接着拷貝 Positive matches
中列出的信息:性能優化
DispatcherServletAutoConfiguration EmbeddedServletContainerAutoConfiguration ErrorMvcAutoConfiguration HttpEncodingAutoConfiguration HttpMessageConvertersAutoConfiguration JacksonAutoConfiguration JmxAutoConfiguration MultipartAutoConfiguration ServerPropertiesAutoConfiguration PropertyPlaceholderAutoConfiguration ThymeleafAutoConfiguration WebMvcAutoConfiguration WebSocketAutoConfiguration
而後來更新項目配置,顯式地引入這些組件,引入以後,再運行一下應用確保沒有錯誤發生:服務器
@Configuration @Import({ DispatcherServletAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, ErrorMvcAutoConfiguration.class, HttpEncodingAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, JmxAutoConfiguration.class, MultipartAutoConfiguration.class, ServerPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, ThymeleafAutoConfiguration.class, WebMvcAutoConfiguration.class, WebSocketAutoConfiguration.class, }) public class SampleWebUiApplication {
在上面的代碼中,咱們能夠刪掉咱們不須要的組件信息,來提升應用的性能,好比在個人項目中,不須要 JMX 和 WebSocket 功能,我就刪掉了它們。刪掉以後,再次運行項目,確保一切正常。
默認狀況下,Spring Boot 使用 Tomcat 來做爲內嵌的 Servlet 容器。咱們能夠啓動項目,而後用 VisualVM 或者 JConsole 來查看應用所佔的內存狀況:
以上是我使用 Spring Boot 的默認方式啓動應用後,用 VisualVM 監控到的內存的佔用狀況:堆內存佔用 110M,16 個線程被開啓。
能夠將 Web 服務器切換到 Undertow 來提升應用性能。Undertow 是一個採用 Java 開發的靈活的高性能 Web 服務器,提供包括阻塞和基於 NIO 的非堵塞機制。Undertow 是紅帽公司的開源產品,是 Wildfly 默認的 Web 服務器。首先,從依賴信息裏移除 Tomcat 配置:
<exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions>
而後添加 Undertow:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
啓動項目後,用 VisualVM 監控到的信息顯示:堆內存佔用 90M,13個線程被開啓。
這些都是咱們在項目開發中使用到的一些優化 Spring
Boot 應用的小技巧,對於大的應用性能的提升仍是很明顯的。你們能夠嘗試一下,而後告訴咱們你的測試結果。
最後,附上代碼,你們能夠去這裏下載:spring-boot-performance。
文中大部份內容參考英國一個架構師的博客 和 DZone 近期發佈的文章,在此感謝兩位大牛。參考文章及連接:
(1)Spring Boot 性能優化:Spring Boot Performance;
(2)Spring Boot 內存優化:Spring Boot Memory Performance。
(3)https://www.techempower.com/benchmarks/;
(4)Spring 應用程序優化:Optimizing Spring Framework for App Engine Applications。
OneAPM 爲您提供端到端的 Java 應用性能解決方案,咱們支持全部常見的 Java 框架及應用服務器,助您快速發現系統瓶頸,定位異常根本緣由。分鐘級部署,即刻體驗,Java 監控歷來沒有如此簡單。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客。