gpt4 book ai didi

当 beans 嵌套在 jar 中时,Spring 启动性能显着降低

转载 作者:行者123 更新时间:2023-12-05 07:48:02 25 4
gpt4 key购买 nike

我们的 Web 应用程序中有数千个 Spring bean,我们使用的是 Spring 4.2.4 版。我们最近更改了打包方案,并注意到当加载的 Spring bean 嵌套在 jar 中时,我们的应用程序启动时间变得更慢。

在分析时,我们发现热点位于封闭的堆栈跟踪中,每个候选 bean 都会在 jar 中创建一个新的输入流。这发生在 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents 内部,它遍历每个资源并获取 MetadataReader。

我们能找到解决方法的唯一方法是更改​​我们的打包方案,使我们的 spring bean 不在 jar 中,而是分解到 webapp 的 WEB-INF/classes 目录中。

我四处搜索,很惊讶我找不到其他人遇到过这个问题。有人知道这是否是 Spring 正在跟踪的错误吗?还是大量使用 Spring 意味着类应该分解到 webapp 的 WEB-INF/classes 目录中只是最佳实践?

"localhost-startStop-1" #21 daemon prio=5 os_prio=0 tid=0x00007f289c3c1800 nid=0x6bb5 runnable [0x00007f28c94c2000]
java.lang.Thread.State: RUNNABLE
at java.util.zip.ZipFile.getEntry(Native Method)
at java.util.zip.ZipFile.getInputStream(ZipFile.java:355)
- eliminated <0x00000000f2ae2240> (a sun.net.www.protocol.jar.URLJarFile)
at java.util.jar.JarFile.getInputStream(JarFile.java:447)
- locked <0x00000000f2ae2240> (a sun.net.www.protocol.jar.URLJarFile)
at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:162)
at org.springframework.core.io.UrlResource.getInputStream(UrlResource.java:168)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:50)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:98)
at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:102)
- locked <0x00000000b445f1a8> (a org.springframework.core.type.classreading.CachingMetadataReaderFactory$1)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:279)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:248)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:87)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1411)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:168)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:138)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:609)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:510)
- locked <0x00000000b4484ac0> (a java.lang.Object)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)

最佳答案

我从来没有经历过这种行为,我总是把 bean 装进 jar 里(但不是成千上万个......)。

CachingMetadataReaderFactory 应该缓存每个资源的元数据以避免多次打开同一个 jar。

它的默认缓存限制为 256(资源)。这可能是你的情况太低了吗?

您可以通过创建自己的 CachingMetadataReaderFactory bean 并增加限制来更改此设置。

或者您可以在该类中设置一些断点,以查看缓存中的条目何时被逐出或找不到缓存条目。

关于当 beans 嵌套在 jar 中时,Spring 启动性能显着降低,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38979560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com