亲调亲测有效的Springboot 性能优化

SpringBoot 是一个快速开发框架,能够快速的整合第三方框架,简化 XML 配置,全部采用注解形式,内置 Tomcat 容器, 帮助开发者能够实现快速开发,SpringBoot 的 Web 组件 默认集成的是 SpringMVC 框架。尽管 SpringBoot 拥有这么多的优点,但也存在性能问题,这并不和它拥有如此多的优点相冲突,应用程序性能只有更优,没有最优。对于 SpringBoot 性能优化可以从注解 @SpringBootApplication 上优化,Servlet 容器上优化, JVM 上优化等等。我们分别从这三方面进行优化。

测试机器信息:

OS :Windows 10 专业版 CPU :Intel® Core™ i5-3230M @2.6GHz RAM :8 GB ROM :120G SSD + 500G HDD JDK :Java version “1.8.0_171” Eclipse :Eclipse Java EE IDE for Web Developers 4.7.3a MySQL :MySQL Version 5.6.15

一、优化注解 @SpringBootApplication

@SpringBootApplication 是 Springboot 整合的一个复合注解,作用相当于 @Configuration + @EnableAutoConfiguration + @ComponentScan ,这个可以查看 @SpringBootApplication 源码得知,其中有一句 This is a convenience annotation that is equivalent to declaring {@code @Configuration},{@code @EnableAutoConfiguration} and {@code @ComponentScan} 说的就是这个意思。

/*
 * Copyright 2012-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;

/**
 * Indicates a {@link Configuration configuration} class that declares one or more
 * {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
 * auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
 * annotation that is equivalent to declaring {@code @Configuration},
 * {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 1.2.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
  @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

 /**
  * Exclude specific auto-configuration classes such that they will never be applied.
  * @return the classes to exclude
  */
 @AliasFor(annotation = EnableAutoConfiguration.class)
 Class<?>[] exclude() default {};

 /**
  * Exclude specific auto-configuration class names such that they will never be
  * applied.
  * @return the class names to exclude
  * @since 1.3.0
  */
 @AliasFor(annotation = EnableAutoConfiguration.class)
 String[] excludeName() default {};

 /**
  * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
  * for a type-safe alternative to String-based package names.
  * @return base packages to scan
  * @since 1.3.0
  */
 @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
 String[] scanBasePackages() default {};

 /**
  * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
  * scan for annotated components. The package of each class specified will be scanned.
  * <p>
  * Consider creating a special no-op marker class or interface in each package that
  * serves no purpose other than being referenced by this attribute.
  * @return base packages to scan
  * @since 1.3.0
  */
 @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
 Class<?>[] scanBasePackageClasses() default {};

}

由于其中包括有包扫描的注解 @ComponentScan ,这会导致项目启动时间变长(启动一个大的应用程序或做大量的集成测试启动应用程序时,影响会特别明显),会加载一些多余的实例(Beans),也会增加 CPU 消耗。

所以可以将 @SpringBootApplication 注解改为 @EnableAutoConfiguration + @Configuration + 在我们需要的 bean 上进行显式配置注解。

通过实际使用 @SpringBootApplication 注解 和 使用 @EnableAutoConfiguration + @Configuration 注解分别各测试启动 5 次 记录实际启动时间,最后取 5 次的平均时间来比较性能的变化,JVM 各参数默认,测试的详细数据见下。

测试项目使用 @SpringBootApplication 注解使用 @EnableAutoConfiguration + @Configuration 注解
第一次测试耗时19.742s/20.867s18.160s/19.291s
第二次测试耗时19.407s/20.563s18.388s/19.496s
第三次测试耗时21.734s/22.90318.308s/19.721s
第四次测试耗时19.908s/21.090s18.576s/19.708s
第五次测试耗时19.456s/20.650s18.418s/19.699s
平均耗时20.049s/21.215s18.370s/19.583s

表格说明:此表基于上述环境测试的真实值,平均耗时取有效小数 5 位。19.742s/20.867s :表示 应用启动耗时 19.742 秒,JVM 启动耗时 20.867 秒。  通过上述测试数据发现使用 @EnableAutoConfiguration + @Configuration 注解 可以提高应用程序启动的性能。

二、将 Servlet 容器由 Tomcat 变成 Undertow

默认情况下 Spring Boot 使用 Tomcat 来作为内嵌的 Servlet 容器,我们可以将 Web 服务器切换到 Undertow 来提高应用性能。Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。接下来我们使用 Jmeter 分别测试使用 Tomcat 容器 和 Undertow 容器在同一个查询数据库信息的接口下的各自的并发量。设置 JVM 参数:-server -XX:+PrintGCDetails -Xms2048m -Xmx2048m,测试数据如下。

测试项目Tomcat 容器Undertow 容器
第一次吞吐量测试315.3/sec395.0/sec
第二次吞吐量测试421.6/sec453.2/sec
第三次吞吐量测试327.8/sec448.8/sec
第四次吞吐量测试351.4/sec340.0/sec
第五次吞吐量测试431.1/sec433.2/sec
平均吞吐量369.44/sec414.04/sec

表格说明:此表基于上述环境测试的真实值,平均吞吐量取有效小数 5 位。  由上表数据可以看出将 Tomcat 容器换为 Undertow 容器将会提高应用性能。

三、JVM 调优

关于 JVM 调优需要了解服务器基本参数配置,JVM 基本组成结构,垃圾回收算法,垃圾回收机制,JVM 调优工具,调优经验等等等,这里不详细列举。  这里就以 JVM 参数 -server -XX:+PrintGCDetails -Xms512m -Xmx512m-server -XX:+PrintGCDetails -Xms2048m -Xmx2048m 为例,还是测试吞吐量,对于参数 -server -XX:+PrintGCDetails -Xms2048m -Xmx2048m 的数据从 Tomcat 容器下吞吐量的测试得来,就不做重复测试了,然后测试参数 -server -XX:+PrintGCDetails -Xms512m -Xmx512m 在 Tomcat 容器下的吞吐量,测试数据见下表。

测试项目Tomcat 512MTomcat 2048M
第一次吞吐量测试300.5/sec315.3/sec
第二次吞吐量测试293.5/sec421.6/sec
第三次吞吐量测试282.6/sec327.8/sec
第四次吞吐量测试302.8/sec351.4/sec
第五次吞吐量测试309.5/sec431.1/sec
平均吞吐量297.78/sec369.44/sec

表格说明:此表基于上述环境测试的真实值,平均吞吐量取有效小数 5 位。  数据说明 JVM 参数 -server -XX:+PrintGCDetails -Xms2048m -Xmx2048m-server -XX:+PrintGCDetails -Xms512m -Xmx512m 要优。进行 JVM 调优是一个谨慎细致的过程,需要慢慢的试,直到当前最优为止。


作者:lytao123

来源链接:

https://blog.csdn.net/qq_24598601/article/details/89314807

cefafd5c31bacd74be1a625b7f6dcf8f.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值