Spring Boot performance optimization

The Spring Framework provides enterprise software developers with generic solutions to common problems, including those that may not be realized in future development. However, the J2EE projects it built became increasingly bloated and gradually replaced by Spring Boot. Spring Boot makes it faster to create and run projects, and more and more people are using it now. We've used Spring Boot in several projects, and today we're going to discuss how to improve the performance of Spring Boot applications.

First of all, let's start with a problem I encountered in development before. While looking at the project run log, I stumbled upon a problem. The log shows that the project always loads the Velocity template engine, but in fact the project is a REST Service project with no web pages. So I spent a bit of time trying to figure out what caused this problem and how to improve the performance of my Spring Boot application. After searching for relevant information, I came to the following conclusions:

 

Problems caused by automatic component scanning

By default, we will use the  @SpringBootApplication  annotation to automatically obtain the configuration information of the application, but this will also bring some side effects to the application. After using this annotation, it will trigger auto-configuration (  auto-configuration  ) and component scanning (  component scanning  ), which is the same as using the three annotations @Configuration, @EnableAutoConfiguration and @ComponentScan. While doing so brings convenience to development, it also has two impacts:

1. It will lead to longer project startup time. The impact is especially noticeable when launching a large application, or launching an application that will do a lot of integration testing.

2. Some unnecessary redundant instances (beans) will be loaded.

3. It will increase CPU consumption.

For the above two cases, we can remove the @SpringBootApplication and @ComponentScan annotations to disable automatic component scanning, and then explicitly configure on the beans we need:

 

// Remove @SpringBootApplication and @ComponentScan, use @EnableAutoConfiguration instead
@Configuration
@EnableAutoConfiguration
public class SampleWebUiApplication {
    // ...
    // Explicitly configured with @Bean annotation to be scanned by Spring
    @Bean
    public MessageController messageController(MessageRepository messageRepository) {
        return new MessageController(messageRepository);
    }

 

 

 

How to avoid problems caused by automatic component scanning

We mentioned above that the effect of the @SpringBootApplication annotation is equivalent to that of the @EnableAutoConfiguration annotation, which means that it can also bring about the above three problems. To avoid these problems, we need to know what the list of components we need is, and we can use -Ddebug to help us clearly locate:

 

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 性能优化

以上是我使用 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 应用的小技巧,对于大的应用性能的提高还是很明显的。大家可以尝试一下,然后告诉我们你的测试结果。

最后,附上代码,大家可以去这里下载: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 官方博客

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327073784&siteId=291194637