如果你的spring-boot应用里tomcat线程耗cpu较高,并主要耗在做读取jar的操作上(堆栈类似下面),可能跟我们遇到同样的问题。

    CRC32.update(byte[], int, int) line: 76
JarInputStream(ZipInputStream).read(byte[], int, int) line: 200
JarInputStream.read(byte[], int, int) line: 207
JarInputStream(ZipInputStream).closeEntry() line: 140
JarInputStream(ZipInputStream).getNextEntry() line: 118
JarInputStream.getNextEntry() line: 142
JarInputStream.getNextJarEntry() line: 179
JarWarResourceSet.getArchiveEntries(boolean) line: 112
JarWarResourceSet(AbstractArchiveResourceSet).getResource(String) line: 256
StandardRoot.getResourceInternal(String, boolean) line: 280
CachedResource.validateResource(boolean) line: 95
Cache.getResource(String, boolean) line: 69
StandardRoot.getResource(String, boolean, boolean) line: 215
StandardRoot.getResource(String) line: 205
Mapper.internalMapWrapper(Mapper$ContextVersion, CharChunk, MappingData) line: 1027
Mapper.internalMap(CharChunk, CharChunk, String, MappingData) line: 842
Mapper.map(MessageBytes, MessageBytes, String, MappingData) line: 698
CoyoteAdapter.postParseRequest(Request, Request, Response, Response) line: 672
CoyoteAdapter.service(Request, Response) line: 344
Http11Processor.service(SocketWrapperBase<?>) line: 784
Http11Processor(AbstractProcessorLight).process(SocketWrapperBase<?>, SocketEvent) line: 66
AbstractProtocol$ConnectionHandler<S>.process(SocketWrapperBase<S>, SocketEvent) line: 802
NioEndpoint$SocketProcessor.doRun() line: 1410
NioEndpoint$SocketProcessor(SocketProcessorBase<S>).run() line: 49
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1142
ThreadPoolExecutor$Worker.run() line: 617
TaskThread$WrappingRunnable.run() line: 61
TaskThread(Thread).run() line: 745

这种情况只发生在 spring-boot 1.4.x版本(及1.3.x版本,更早的没有确认),1.5.x已经没有这个问题。

主要的改变在org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory的内部类StoreMergedWebXmlListeneronStart方法:

// TomcatEmbeddedContext 启动时触发了该监听器
private void onStart(Context context) {
ServletContext servletContext = context.getServletContext();
if (servletContext.getAttribute(MERGED_WEB_XML) == null) {
servletContext.setAttribute(MERGED_WEB_XML, getEmptyWebXml());
}
// 注意最后这句,1.5.3版本已经去掉了这句,它导致变慢
TomcatResources.get(context).addClasspathResources();
}

addClasspathResources方法里对于jar资源的处理,不同的tomcat版本方式有所不同,spring-boot 中如果使用嵌入式的 tomcat8 的话这些jar资源会记录到StandardRoot里的jarResources集合里,它们会被定时清理。

tomcat容器的后台线程(ContainerBackgroundProcessor)会触发StandardRoot里的清理逻辑

    public void backgroundProcess() {
cache.backgroundProcess();
gc();
} public void gc() {
for (List<WebResourceSet> list : allResources) {
for (WebResourceSet webResourceSet : list) {
webResourceSet.gc();
}
}
} // JarWarResourceSet里的gc方法
public void gc() {
synchronized (archiveLock) {
if (archive != null && archiveUseCount == 0) {
try {
archive.close();
} catch (IOException e) {
// Log at least WARN
}
archive = null;
archiveEntries = null;
}
}
}

请求过来时,Mapper阶段会根据请求路径去找映射的资源,Cache不管命中还是未命中,都会对资源进行validate,在validateResource时要去遍历WebResourceRoot里所有的资源(包括所有的jar资源),若应用依赖的jar比较多时,会导致cpu较高。

spring-boot 1.5 版本里不会再将 BOOT-INF/lib 下的所有jar添加到tomcat的WebResourceRoot里,升级到1.5.3后这个情况没有再发生。

http://hongjiang.info/spring-boot-1-4-bug/

spring-boot 1.4.x遇到的cpu高的问题的更多相关文章

  1. Spring boot 1.3.5 RELEASE 官方文档中文翻译--Part2:新手入门

    Part II. 新手入门 如果你刚刚开始学习Spring boot或"普通"的Spring,这部分非常适合你!在这里,我们回答了最基础的"什么是?".&quo ...

  2. spring boot 1.x完整学习指南(含各种常见问题servlet、web.xml、maven打包,spring mvc差别及解决方法)

    spring boot 入门 关于版本的选择,spring boot 2.0开始依赖于 Spring Framework 5.1.0,而spring 5.x和之前的版本差距比较大,而且应该来说还没有广 ...

  3. 【转】Spring Boot干货系列:(一)优雅的入门篇

    转自Spring Boot干货系列:(一)优雅的入门篇 前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做 ...

  4. Spring Boot干货系列:(一)优雅的入门篇

    Spring Boot干货系列:(一)优雅的入门篇 2017-02-26 嘟嘟MD 嘟爷java超神学堂   前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社 ...

  5. 《Spring Boot官方指南》(二)入门

    如果您刚开始接触Spring Boot,或者简称’Spring’, 这个部分对您来说非常有用.这个部分提供了“是什么?”,“怎么做?”和 “为什么?”的解释.您除了会阅读一份附带Spring Boot ...

  6. Spring boot参考指南

    介绍 转载自:https://www.gitbook.com/book/qbgbook/spring-boot-reference-guide-zh/details 带目录浏览地址:http://ww ...

  7. 【spring boot】SpringBoot初学(1) - Hello World

    前言 此文只是记录自己简单学习spring boot的笔记.所以,文章很多只是初步理解,可能存在严重错误. 一.Spring boot的初步理解 1.spring boot的目标 (摘自:spring ...

  8. Spring Boot从入门到精通(八)日志管理实现和配置信息分析

    Spring Boot对日志的处理,与平时我们处理日志的方式完全一致,它为Java Util Logging.Log4J2和Logback提供了默认配置.对于每种日志都预先配置使用控制台输出和可选的文 ...

  9. spring boot springMVC扩展配置 。WebMvcConfigurer ,WebMvcConfigurerAdapter

    摘要: 在spring boot中 MVC这部分也有默认自动配置,也就是说我们不用做任何配置,那么也是OK的,这个配置类就是 WebMvcAutoConfiguration,但是也时候我们想设置自己的 ...

  10. 是时候为Spring Boot 3.0做准备了

    2018年2月28日Spring Boot进入2.0时代,距今已经超过4年了. 2022 年 11 月 Spring Boot 3.0 将正式发布,它将基于 Spring Framework 6.0, ...

随机推荐

  1. StringUtils常用方法介绍

    要使用StringUtils类,首先需要导入:import org.apache.commons.lang.StringUtils;这个包 在maven项目中需要添加下面这个依赖: <depen ...

  2. IDEA下载与安装

    IntelliJ IDEA号称当前Java开发效率最高的IDE工具. IntelliJ IDEA有两个版本:社区版(Community)和旗舰版(Ultimate). 社区版 是免费的.开源的,但功能 ...

  3. 5w5:第五周程序填空题1

    描述 写一个MyString 类,使得下面程序的输出结果是: 1. abcd-efgh-abcd- 2. abcd- 3. 4. abcd-efgh- 5. efgh- 6. c 7. abcd- 8 ...

  4. python3好用的mysql.connector库

    python3好用的mysql.connector库 from mysql.connector import connect #建立mysql连接,生成一个mysql.connector对象 conn ...

  5. 题解 P4140 【奇数国 】

    题目链接 首先,按照题意,把前$60$个素数打出来$[2$ $-$ $281]$. 因为只有$60$个,再加上本宝宝极其懒得写线性筛于是每一个都$O(\sqrt{n})$暴力筛就好了. 代码如下: # ...

  6. luoguP4782 [模板]2-SAT问题

    https://www.luogu.org/problemnew/show/P4782 2-SAT模板,输出方案只需判断 \(a\) 和 \(a + n\) 两个点所在的 scc 编号大小就可以了 # ...

  7. 洛谷P4494 [HAOI2018]反色游戏(tarjan)

    题面 传送门 题解 我们先来考虑一个联通块,这些关系显然可以写成一个异或方程组的形式,形如\(\oplus_{e\in edge_u}x_e=col_u\) 如果这个联通块的黑色点个数为奇数,那么显然 ...

  8. P1129 [ZJOI2007]矩阵游戏(二分图,网络流)

    传送门 这推导过程真的有点可怕的说……完全想不出来…… 最终状态是$(1,1),(2,2),(3,3)...(n,n)$都有一个黑点 我们可以理解为每一个行和列都形成了一个匹配 换句话说,只要$n$行 ...

  9. [Swift]八大排序算法(四):堆排序

    排序分为内部排序和外部排序. 内部排序:是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 外部排序:指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存 ...

  10. Linux 意外操作后如何进行数据抢救

    Linux 意外操作后如何进行数据抢救 在 GUI 中使用  shift + delete  组合键或是 CLI 下使用 rm -rf 删除选项,这个文件并没有从硬盘(或是其它存储设备)上彻底销毁.当 ...