【发布时间】:2015-10-26 18:08:24
【问题描述】:
我有一个 spring boot java servlet,它在 Jetty 下运行良好,但在我们的目标部署环境 Tomcat 下运行时出现性能问题。
- JAXB 解组遇到瓶颈,因为 ServiceLoader 花费大量时间查找要使用的 TransformerFactory 实现。 (YourKit profiling showing the look up for the TransformerFactory implementation)
- Saxon 是转换实现,jar 包含在 tomcat/webapps/myapp/WEB-INF/lib 中,并具有正确的 META-INF/services 文件
- 使用 Jetty 作为 servlet 容器时不存在此问题
- 我已经确认在 Jetty 和 Tomcat 下运行我从正确的 jar 中获得了 TransformerFactory 的正确实现
-
将映射显式添加到 Tomcat JAVA_OPTS 选项可以解决问题:
-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl
编辑: 我们在 Jetty 中的 xml 获取/转换时间大约是 5 秒,而在 Tomcat 下是 20 秒,这直接是由于类加载器搜索了我们的 TransformerFactory。
我可以通过在我们的 servlet 配置中明确指定 TransformerFactory 来解决这个问题,但我的问题仍然存在: 为什么 Tomcat 需要这个显式 setProperty 而 Jetty 容器不需要?
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
return application.sources(Application.class);
}
对不起,如果这是一个初级问题,我是一只学习 Java 和网络应用程序/servlet 技巧的老 C++ 狗。
【问题讨论】:
-
第 4 个问题:“运行可执行的 .jar 或 .war 文件时”是指这些文件使用嵌入式码头而不是嵌入式 tomcat?
-
当我进行测试时,他们使用的是嵌入式 Tomcat。在我所有的测试中,Jetty 一直都是外部的。
-
我还阅读了有关 Jetty 和 Tomcat 的类加载器的文档。从这些来看,我不希望有任何区别,因为两个容器都必须遵守标准中设置的 servlet 容器的类加载器规则。
-
太板了,你需要了解一下这个工厂是如何解决的,也许是注释扫描?为什么不以编程方式设置工厂?
-
已编辑以尝试提供更多数据并缩小问题范围。我已经解决了这个问题,但感觉就像一个黑客,可能有更合适的方法来解决它。另外,我非常好奇为什么 Jetty 在没有额外设置的情况下也能正常工作,而只有 Tomcat 需要它。
标签: java tomcat spring-boot jetty saxon