SpringBoot调优
1、增加内嵌Tomcat容器的连接数
@Configuration
public class TomcatConfig {@Value("${server.port}")public int port;@Beanpublic ConfigurableServletWebServerFactory configurableServletWebServerFactory(){TomcatServletWebServerFactory tomcatFactory = new TomcatServletWebServerFactory();tomcatFactory.addConnectorCustomizers(new MyTomcatConnectorCustomizer());tomcatFactory.setPort(port);return tomcatFactory;}class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer {public void customize(Connector connector) {Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();//设置最大连接数protocol.setMaxConnections(20000);//设置最大线程数protocol.setMaxThreads(2000);protocol.setConnectionTimeout(30000);}}
}
也可以通过yml配置文件
server.tomcat.max-connections=20000 # Maximum number of connections that the server accepts and processes at any given time.
server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header.
server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content.
server.tomcat.max-threads=2000 # Maximum number of worker threads.
server.tomcat.min-spare-threads=0 # Minimum number of worker threads.
2、使用异步,业务代码添加@async注解,启动类增加@EnableAsync注解
@Async是spring为了方便开发人员进行异步调用的出现的,在方法上加入这个注解,spring会从线程池中获取一个新的线程来执行方法,实现异步调用,可以在类和方法上加注解。在类上表示所有方法都是异步 ,所以建议在方法方法上加,比如在service的方法上,这样controller就可以调用之后直接返回结果,提升吞吐量。
@EnableAsync表示开启对异步任务的支持,可以放在springboot的启动类上,也可以放在自定义线程池的配置类上,具体看下文https://www.cnblogs.com/fzhblog/p/14012401.html
3、默认Tomcat的容器改为Undertow(Tomcat:5000,Undertow:8000)
undertow,jetty和tomcat可以说是javaweb项目当下最火的三款服务器,tomcat是apache下的一款重量级的服务器,不用多说历史悠久,经得起实践的考验。然而:当下微服务兴起,spring boot ,spring cloud 越来越热的情况下,选择一款轻量级而性能优越的服务器是必要的选择。spring boot 完美集成了tomcat,jetty和undertow,本文将通过对jetty和undertow服务器的分析以及测试,来比较两款服务器的性能如何。
值得一提的是jetty和undertow都是基于NIO实现的高并发轻量级的服务器,支持servlet3.1和websocket。所以,有必要先了解下什么是NIO。
NIO(非阻塞式输入输出)
Channel
Selector
Buffer
Acceptor
Client和Server只向Buffer读写数据不关注数据的流向,数据通过Channel通道进行流转。而Selector是存在与服务端的,用于Channel的注册以此实现数据I/O操作。Acceptor负责接受所以的连接通道并且注册到Channel中。而整个过程客户端与服务端是非阻塞的也就是异步操作。
下面是压力测试对比图:
从中可以看出在高负载下Undertow的吞吐量高于Jetty而且随着压力增大Jetty和Undertow成功率差距会拉大。而在负载不是太大情况下服务器处理能力差不多,jetty还略微高于Undertow。而tomcat的负载能力似乎和Undertow很接近。
对比三个服务器发现在Undertow在负载过重情况下比Jetty和Tocmat更加顽强,实践证明在负载继续加大情况下Undertow的成功率高于其它两者,但是在并发不是太大情况下三款服务器整体来看差别不大。
————————————————
版权声明:本文为CSDN博主「芸灵fly」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38187317/article/details/81532560
配置pom.xml
<!-- 下面的配置将使用undertow来做服务器而不是tomcat -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
配置application.yml
server:port: 8081# 下面是配置undertow作为服务器的参数undertow:# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程io-threads: 4# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载worker-threads: 20# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理# 每块buffer的空间大小,越小的空间被利用越充分buffer-size: 1024# 是否分配的直接内存direct-buffers: true
配置比较简单,和tomcat使用基本一样
4、不使用@SpringBootApplication,精确指定自动配置类
要想了解SpringBoot的自动配置,我们可以在源码看到相关代码和配置。
SpringBoot关于自动配置的源码在spring-boot-autoconfigure-2.1.x.jar内,打开maven依赖我们可以看见如果想了解SpringBoot为我们做了哪些自动配置,可以通过下面方式查看当前项目中已启用和未启用的自动配置的报告。
运行jar时增加--debug参数:
java -jar xx.jar --debug
在application.properties中设置属性:
debug=true
启动时,通过控制台我们可以看到哪些配置已使用自动配置,哪些配置没有自动配置。
已启用自动配置
未启用自动配置
仔细看上图我们可以发现,相关如
@ConditionalOnClass found required class ... \ @ConditionalOnClass did not find required class ...
的字眼非常多,可见@ConditionalOnClass注解可能在自动配置中起着主要作用,那究竟是如何起作用的呢?
具体详情了解https://www.cnblogs.com/xicent/p/11526438.html
优化方案
因为@SpringBootApplication会启动很多AutoConfiguration,我们可以精确指定
/*** 自定义启动类* @author Blueeyedboy* @create 2022-04-13 11:46 AM**/
@Configuration
@Import({DispatcherServletAutoConfiguration.class,EmbeddedServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class,HttoEncoderAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class,JmxAutoConfiguration.class, MultipartAutoConfiguration.class,ServerPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,ThymeleafAutoConfiguration.class, WebMvcAutoConfiguration.class,WebSocketAutoConfiguration.class
})
public class Application {
}
5、JVM启动参数调优
参考:https://blog.51cto.com/u_13929722/3528710
https://www.csdn.net/tags/MtjaEg4sODEwMTctYmxvZwO0O0OO0O0O.html
关于这些设置的JVM参数是什么意思,请参考第二步中的oracle官方给出的调优文档。
我在这边简单说一下:
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
-Xms1024m (堆最大大小)
-Xmx1024m (堆默认大小)
-Xmn256m (新生代大小)
-Xss256k (棧最大深度大小)
-XX:SurvivorRatio=8 (新生代分区比例 8:2)
-XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)
-XX:+PrintGCDetails (打印详细的GC日志)
知识点:
JDK8之后把-XX:PermSize 和-XX:MaxPermGen移除了,取而代之的是
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
JDK 8开始把类的元数据放到本地化的堆内存(native heap)中,这一块区域就叫Metaspace,中文名叫元空间。
使用本地化的内存有什么好处呢?最直接的表现就是java.lang.OutOfMemoryError: PermGen 空间问题将不复存在,因为默认的类的元数据分配只受本地内存大小的限制,也就是说本地内存剩余多少,理论上Metaspace就可以有多大(貌似容量还与操作系统的虚拟内存有关?这里不太清楚),这解决了空间不足的问题。
不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。
概念
具体来讲:
Java整个堆大小设置,Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代(jdk8为元数据MetaSpace)PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。默认新生代与老年代的比例为 1:2 ,不冲突。
BTW:
1、Sun官方建议年轻代的大小为整个堆的3/8左右, 所以按照上述设置的方式,基本符合Sun的建议。 2、堆大小=年轻代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影响堆大小。3、为什么要按照上面的来进行设置呢? 没有具体的说明,但应该是根据多种调优之后得出的一个结论。
如何确认老年代存活对象大小?
方式1(推荐/比较稳妥):
开启GC日志打印,例配置jvm参数 -XX:+PrintGC 观察多次Full GC后老年代存活对象的大小取平均值为准
方式2:(强制触发FullGC, 会影响线上服务,慎用)
方式1的方式比较可行,但需要更改JVM参数,并分析日志。同时,在使用CMS回收器的时候,有可能不能触发FullGC(只发生CMS GC),所以日志中并没有记录FullGC的日志。在分析的时候就比较难处理。BTW:使用jstat -gcutil工具来看FullGC的时候, CMS GC是会造成2次的FullGC次数增加。 具体可参见之前写的一篇关于jstat使用的文章所以,有时候需要强制触发一次FullGC,来观察FullGC之后的老年代存活对象大小。注:强制触发FullGC,会造成线上服务停顿(STW),要谨慎,建议的操作方式为,在强制FullGC前先把服务节点摘除,FullGC之后再将服务挂回可用节点,对外提供服务在不同时间段触发FullGC,根据多次FullGC之后的老年代内存情况来预估FullGC之后的老年代存活对象大小。
如何触发FullGC ?
使用jmap工具可触发FullGC jmap -dump:live,format=b,file=heap.bin <pid> 将当前的存活对象dump到文件,此时会触发FullGCjmap -histo:live <pid> 打印每个class的实例数目,内存占用,类全名信息.live子参数加上后,只统计活的对象数量. 此时会触发FullGC
补充
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
以下两个参数配置对于测试环境springboot项目就够用了,生产环境可以适当按比例扩大一些。
-Xms256m -Xmx256m -Xmn64m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m-Xms256m -Xmx256m -Xmn128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m
示例:
java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC newframe-1.0.0.jar
SpringBoot调优相关推荐
- SpringBoot项目优化和Jvm调优(亲测,真实有效)
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:星朝 原文:cnblogs.com/jpfss/p/9753 ...
- SpringBoot 深度调优,让你的项目飞起来!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:星朝 cnblogs.com/jpfss/p/9753215 ...
- SpringBoot项目优化和Jvm调优(楼主亲测,真实有效)
今日推荐Spring新版本抛弃JVM,可独立部署,网友:要自立门户???国内大神成功给手机装上了 Win11,代码已开源!Fluent Mybatis 牛逼!Nginx 常用配置清单这玩意比Threa ...
- SpringBoot项目优化和Jvm调优及VisualVM远程连接监控JVM(JMX连接)
项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情. 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行. 在这边有一篇比较好的文章,推荐给大家! Spring ...
- springboot不会运行gc_SpringBoot项目深度优化和Jvm调优
点击上方"Java学习之道",选择"关注"公众号 每天上班,干货准时送达! 本文作者:星朝 本文来源:www.cnblogs.com/jpfss/p/97532 ...
- java项目processes设置,Jvm调优和SpringBoot项目优化的详细教程
参考文章 1.先看一下未设置JVM参数的情况,默认情况下,没有设置任何Jvm参数. 2.设置Jvm参数. 配置参数: 关于这些设置的JVM参数是什么意思,参考Jvm调优. -XX:MetaspaceS ...
- springboot不会运行gc_SpringBoot 和JVM 调优(深度好文,建议收藏)
点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情. 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方 ...
- springboot不会运行gc_SpringBoot 深度调优,让你的项目飞起来!
项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情. 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行. 一.修改配置文件 关于修改配置文件applicati ...
- SpringBoot集成Kafka并调优
1. 集成 SpringBoot SpringBoot 是一个在 JavaEE 开发中非常常用的组件.可以用于 Kafka 的生产者,也可以用于 Kafka 的消费者. 1.1 在 IDEA 中安装 ...
- SpringBoot中Web容器配置和调优
SpringBoot的启动容器主要是Tomcat,Jetty,Undertow三种容器类型,具体的配置类为 org.springframework.boot.autoconfigure.web.Ser ...
最新文章
- Python的零基础超详细讲解(第五天)-Python的运算符
- 【FPGA】SRIO IP核系统总览以及端口介绍(三)(Messaging Port、User-Defined Port介绍)
- Xamarin XAML语言教程基本页面ContentPage占用面积内容页面的派生关系与属性
- Directx 顶点和顶点缓存
- 我们不应歧视任何编程语言,她们都是萌娘!(有图有真相)
- OpenCV多机校准Multi-camera Calibration
- 使用 ASMCMD 工具管理ASM目录及文件
- 支付宝2017年个人账单明天发布,你小心脏准备好了吗?
- Python基础(八)--迭代,生成器,装饰器与元类
- “安全宝”,云安全服务
- log4j+flume+HDFS实现日志存储
- 如何在S函数中对变量或者输入信号进行求导
- 【pnpm】pnpm : 无法加载文件 C:\Users\M_F15\AppData\Roaming\npm\pnpm.ps1
- 网易云音乐显示网络异常
- cad字体安装_一键自动替换CAD图纸缺失的字体
- rufus(u盘引导盘制作工具) v3.5.1497
- Linux编译DuiLib库报error: no matches converting function ‘ItemComareFunc’ to type ‘__compar_d_fn_t错误解决
- 计算机命令行操作系统,什么是命令提示符以及如何打开它
- 坐标转换中的七参数详谈
- python 计时器模块_python中计时器