paulwong

          Spring Boot 性能優(yōu)化

          摘要
          Spring 框架給企業(yè)軟件開發(fā)者提供了常見問題的通用解決方案,包括那些在未來開發(fā)中沒有意識到的問題。但是,它構(gòu)建的 J2EE 項(xiàng)目變得越來越臃腫,逐漸被 Spring Boot 所替代。Spring Boot 讓我們創(chuàng)建和運(yùn)行項(xiàng)目變得更為迅速,現(xiàn)在已經(jīng)有越來越多的人使用它。我們已經(jīng)在幾個項(xiàng)目中使用了 Spring Boot ,今天我們就來一起討論一下如何改進(jìn) Spring Boot 應(yīng)用的性能。

          Spring 框架給企業(yè)軟件開發(fā)者提供了常見問題的通用解決方案,包括那些在未來開發(fā)中沒有意識到的問題。但是,它構(gòu)建的 J2EE 項(xiàng)目變得越來越臃腫,逐漸被 Spring Boot 所替代。Spring Boot 讓我們創(chuàng)建和運(yùn)行項(xiàng)目變得更為迅速,現(xiàn)在已經(jīng)有越來越多的人使用它。我們已經(jīng)在幾個項(xiàng)目中使用了 Spring Boot ,今天我們就來一起討論一下如何改進(jìn) Spring Boot 應(yīng)用的性能。

          首先,從之前我在開發(fā)中遇到的一個問題說起。在一次查看項(xiàng)目運(yùn)行日志的時候,我偶然發(fā)現(xiàn)了一個問題,日志里顯示這個項(xiàng)目總是加載 Velocity 模板引擎,但實(shí)際上這個項(xiàng)目是一個沒有 web 頁面的 REST Service 項(xiàng)目。于是我花了一點(diǎn)時間去尋找產(chǎn)生這個問題的原因,以及如何改進(jìn) Spring Boot 應(yīng)用的性能。在查找了相關(guān)的資料后,我得出的結(jié)論如下:

          組件自動掃描帶來的問題

          默認(rèn)情況下,我們會使用 @SpringBootApplication 注解來自動獲取的應(yīng)用的配置信息,但這樣也會給應(yīng)用帶來一些副作用。使用這個注解后,會觸發(fā)自動配置( auto-configuration )和 組件掃描 ( component scanning),這跟使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三個注解的作用是一樣的。這樣做給開發(fā)帶來方便的同時,也會有兩方面的影響:

          1、會導(dǎo)致項(xiàng)目啟動時間變長。當(dāng)啟動一個大的應(yīng)用程序,或?qū)⒆龃罅康募蓽y試啟動應(yīng)用程序時,影響會特別明顯。

          2、會加載一些不需要的多余的實(shí)例(beans)。

          3、會增加 CPU 消耗。

          針對以上兩個情況,我們可以移除 @SpringBootApplication 和 @ComponentScan 兩個注解來禁用組件自動掃描,然后在我們需要的 bean 上進(jìn)行顯式配置:

          // 移除 @SpringBootApplication and @ComponentScan, 用 @EnableAutoConfiguration 來替代
          @Configuration
          @EnableAutoConfiguration
          public class SampleWebUiApplication {

              
          // 

              
          // 用 @Bean 注解明確顯式配置,以便被 Spring 掃描到
              @Bean
              
          public MessageController messageController(MessageRepository messageRepository) {
                  
          return new MessageController(messageRepository);
              }

          如何避免組件自動掃描帶來的問題

          我們在上面提到,@SpringBootApplication 注解的作用跟 @EnableAutoConfiguration 注解的作用是相當(dāng)?shù)模蔷鸵馕吨材軒砩鲜龅娜齻€問題。要避免這些問題,我們就要知道我們需要的組件列表是哪些,可以用 -Ddebug 的方式來幫助我們明確地定位:

          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

          然后來更新項(xiàng)目配置,顯式地引入這些組件,引入之后,再運(yùn)行一下應(yīng)用確保沒有錯誤發(fā)生:

          @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 {}


          在上面的代碼中,我們可以刪掉我們不需要的組件信息,來提高應(yīng)用的性能,比如在我的項(xiàng)目中,不需要 JMX 和 WebSocket 功能,我就刪掉了它們。刪掉之后,再次運(yùn)行項(xiàng)目,確保一切正常。

          將Servlet容器變成Undertow

          默認(rèn)情況下,Spring Boot 使用 Tomcat 來作為內(nèi)嵌的 Servlet 容器。我們可以啟動項(xiàng)目,然后用 VisualVM 或者 JConsole 來查看應(yīng)用所占的內(nèi)存情況:

          Spring Boot 性能優(yōu)化

          以上是我使用 Spring Boot 的默認(rèn)方式啟動應(yīng)用后,用 VisualVM 監(jiān)控到的內(nèi)存的占用情況:堆內(nèi)存占用 110M,16 個線程被開啟。

          可以將 Web 服務(wù)器切換到 Undertow 來提高應(yīng)用性能。Undertow 是一個采用 Java 開發(fā)的靈活的高性能 Web 服務(wù)器,提供包括阻塞和基于 NIO 的非堵塞機(jī)制。Undertow 是紅帽公司的開源產(chǎn)品,是 Wildfly 默認(rèn)的 Web 服務(wù)器。首先,從依賴信息里移除 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>


          啟動項(xiàng)目后,用 VisualVM 監(jiān)控到的信息顯示:堆內(nèi)存占用 90M,13個線程被開啟。

          Spring Boot 性能優(yōu)化

          總結(jié)

          這些都是我們在項(xiàng)目開發(fā)中使用到的一些優(yōu)化 Spring Boot 應(yīng)用的小技巧,對于大的應(yīng)用性能的提高還是很明顯的。大家可以嘗試一下,然后告訴我們你的測試結(jié)果。

          最后,附上代碼,大家可以去這里下載:spring-boot-performance

          文中大部分內(nèi)容參考英國一個架構(gòu)師的博客 和 DZone 近期發(fā)布的文章,在此感謝兩位大牛。參考文章及鏈接:

          (1)Spring Boot 性能優(yōu)化:Spring Boot Performance

          (2)Spring Boot 內(nèi)存優(yōu)化:Spring Boot Memory Performance

          (3)https://www.techempower.com/benchmarks/

          (4)Spring 應(yīng)用程序優(yōu)化:Optimizing Spring Framework for App Engine Applications

          posted on 2016-09-11 16:37 paulwong 閱讀(839) 評論(0)  編輯  收藏 所屬分類: SPRING BOOT

          主站蜘蛛池模板: 扶余县| 锡林郭勒盟| 和龙市| 南昌市| 社会| 盘锦市| 巴塘县| 叶城县| 德格县| 河北区| 六枝特区| 徐闻县| 泰安市| 兰西县| 汉寿县| 兴和县| 成武县| 达孜县| 镇沅| 三河市| 莱阳市| 泰顺县| 安溪县| 邯郸市| 安康市| 曲沃县| 金塔县| 图片| 塔城市| 稻城县| 石台县| 三河市| 南漳县| 讷河市| 攀枝花市| 许昌县| 山东| 阜城县| 鞍山市| 洛阳市| 化州市|