spring boot starter作为jar运行时的ws性能

spring boot starter作为jar运行时的ws性能,spring,maven,soap,spring-boot,spring-ws,Spring,Maven,Soap,Spring Boot,Spring Ws,我们已经注意到,在我们的示例中,SOAP web服务在以相同的方式运行时似乎运行得更快 spring-boot:run 而不是像我们在部署和运行时那样打包JAR java -jar mySpringApp.jar 速度大约是2-3倍,所以很明显,我们希望我们的生活环境能有这样的速度 为了验证这不是我们应用程序中的某个东西,我已经用来自 git源 用JMeter测试这一点也显示了同样的加速。我已经在Windows7Java1.8.0_31和Ubuntu14.04平台上用1.8.0_45-b14

我们已经注意到,在我们的示例中,SOAP web服务在以相同的方式运行时似乎运行得更快

spring-boot:run
而不是像我们在部署和运行时那样打包JAR

java -jar mySpringApp.jar
速度大约是2-3倍,所以很明显,我们希望我们的生活环境能有这样的速度

为了验证这不是我们应用程序中的某个东西,我已经用来自

git源

用JMeter测试这一点也显示了同样的加速。我已经在Windows7Java1.8.0_31和Ubuntu14.04平台上用1.8.0_45-b14测试过了


这似乎只是soap服务的情况,简单html在性能上没有显示任何显著差异。知道是什么原因导致了这种情况吗?

我对此进行了测试,发现应用程序在以下两个代码路径上花费了大量时间:

at org.springframework.boot.loader.LaunchedURLClassLoader$1.hasMoreElements(LaunchedURLClassLoader.java:110)
at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45)
at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54)
at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:354)
at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393)
at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474)
at javax.xml.transform.FactoryFinder$1.run(FactoryFinder.java:327)
at java.security.AccessController.doPrivileged(Native Method)
at javax.xml.transform.FactoryFinder.findServiceProvider(FactoryFinder.java:323)
at javax.xml.transform.FactoryFinder.find(FactoryFinder.java:299)
at javax.xml.transform.TransformerFactory.newInstance(TransformerFactory.java:106)
at com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.<init>(EfficientStreamingTransformer.java:68)
at com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.newTransformer(EfficientStreamingTransformer.java:420)
at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:106)
at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:69)
at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:128)
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:189)
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:60)
at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:92)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:87)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)

这意味着对于每个请求,JRE中的SAAJ实现都会请求一个新的
TransformerFactory
和一个新的
DocumentBuilderFactory
。这些工厂使用定位,这涉及在
META-INF/services
下搜索某些资源。该搜索的性能对从中查找这些资源的类装入器的特性非常敏感。这就是为什么您会看到
mvn-spring-boot:run
和使用可执行JAR之间的区别。特别是,可执行JAR包含嵌入式JAR,从这些嵌入式JAR中查找资源非常昂贵。对于
mvn-spring-boot:run
来说,情况并非如此,这解释了为什么它更快

因为这最终是SAAJ实现的一个问题,所以一个解决方案是使用。要对spring指南中的示例应用程序执行此操作,只需将以下代码添加到
WebServiceConfig

    @Bean
    public SoapMessageFactory messageFactory() {
        return new AxiomSoapMessageFactory();
    }
您还需要添加以下依赖项:

    <dependency>
        <groupId>org.apache.ws.commons.axiom</groupId>
        <artifactId>axiom-impl</artifactId>
        <version>1.2.15</version>
    </dependency>

org.apache.ws.commons.axiom
简化公理
1.2.15

在调查这一点时,我已经尝试过将tomcat替换为jetty并运行爆炸的JAR,但这两种方法都没有产生任何重大影响。我也在Mac上对其进行了测试,并有相同的行为。我真的很好奇,也许会在周末找时间做一些调试。您是否尝试过jvisualvm来检查jvm中的差异?比如最大堆大小,gc活动?也许可以附加一个剖析器来检查时间在哪里。谢谢保罗,我很高兴有人能够重现这一点。java-jar启动的变体中可能有更多的GC活动,但在探查器中运行它时,我可以看到超过10%的执行时间在org.springframework.boot.loader.jar.JarURLConnection.throwFileNotFound()中,当作为spring boot:run运行时,我根本看不到调用这个类。springboot:run是否以不同的方式处理JAR/类加载?我将在周末进一步了解。当使用
java-jar
时,类加载是完全不同的,因为Boot需要处理从嵌套在应用程序jar的
lib
目录中的jar加载类。我已经开了一个办公室,以便我们可以调查。
at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:120)
    @Bean
    public SoapMessageFactory messageFactory() {
        return new AxiomSoapMessageFactory();
    }
    <dependency>
        <groupId>org.apache.ws.commons.axiom</groupId>
        <artifactId>axiom-impl</artifactId>
        <version>1.2.15</version>
    </dependency>