Spring 框架给企业软件开发者提供了常见问题的通用解决方案,包括那些在将来开发中没有意识到的问题。可是,它构建的 J2EE 项目变得愈来愈臃肿,逐渐被 Spring Boot 所替代。Spring Boot 让咱们建立和运行项目变得更为迅速,如今已经有愈来愈多的人使用它。咱们已经在几个项目中使用了 Spring Boot ,今天咱们就来一块儿讨论一下如何改进 Spring Boot 应用的性能。html
首先,从以前我在开发中遇到的一个问题提及。在一次查看项目运行日志的时候,我偶然发现了一个问题,日志里显示这个项目老是加载 Velocity 模板引擎,但实际上这个项目是一个没有 web 页面的 REST Service 项目。因而我花了一点时间去寻找产生这个问题的缘由,以及如何改进 Spring Boot 应用的性能。在查找了相关的资料后,我得出的结论以下:java
##组件自动扫描带来的问题git
默认状况下,咱们会使用 @SpringBootApplication 注解来自动获取的应用的配置信息,但这样也会给应用带来一些反作用。使用这个注解后,会触发自动配置( auto-configuration )和 组件扫描 ( component scanning ),这跟使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三个注解的做用是同样的。这样作给开发带来方便的同时,也会有两方面的影响:github
一、会致使项目启动时间变长。当启动一个大的应用程序,或将作大量的集成测试启动应用程序时,影响会特别明显。web
二、会加载一些不须要的多余的实例(beans)。spring
三、会增长 CPU 消耗。api
针对以上两个状况,咱们能够移除 @SpringBootApplication 和 @ComponentScan 两个注解来禁用组件自动扫描,而后在咱们须要的 bean 上进行显式配置:tomcat
// 移除 @SpringBootApplication and @ComponentScan, 用 @EnableAutoConfiguration 来替代 @Configuration @EnableAutoConfiguration public class SampleWebUiApplication { // ... // 用 @Bean 注解明确显式配置,以便被 Spring 扫描到 @Bean public MessageController messageController(MessageRepository messageRepository) { return new MessageController(messageRepository); }
##如何避免组件自动扫描带来的问题性能优化
咱们在上面提到,@SpringBootApplication 注解的做用跟 @EnableAutoConfiguration 注解的做用是至关的,那就意味着它也能带来上述的三个问题。要避免这些问题,咱们就要知道咱们须要的组件列表是哪些,能够用 -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
而后来更新项目配置,显式地引入这些组件,引入以后,再运行一下应用确保没有错误发生:
@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 功能,我就删掉了它们。删掉以后,再次运行项目,确保一切正常。
##将Servlet容器变成Undertow
默认状况下,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 官方技术博客。
本文转自 OneAPM 官方博客