JAXB 性能在负载下显着下降

问题描述 投票:0回答:1

我们有一堆微服务,它们使用 JAXB 在 XML 有效负载和 Java 对象之间进行编组/取消编组。 在我们的负载测试中,我们注意到性能显着下降,在放置大量日志条目后,我们发现 JAXB 处理(主要是解组部分)有时需要 1 到 3 mills(理应如此),但有时需要几秒钟(甚至 10 到 20 秒)来处理基本相同的有效负载(只有几个元素值不同,使它们独一无二。有效负载不小,但也不大;大约 50KB。

当没有负载时,处理总是很快。我唯一的一个怀疑(没有任何关于 JAXB 内部工作原理的研究)是有一些

syncronized
调用,并且大量线程并行执行相同的操作,这只会阻碍整个事情。

这就是我们解组的方式:

public MyJavaObject toMyJavaObject(String payload) {
    try (StringReader reader = new StringReader(payload)) {
       final StreamSource source = new StreamSource(reader);
       return (MyJavaObject) ((JAXBElement) myMarshaller.unmarshal(source)).getValue();
    }
 }

在哪里创建

myMarshaller
bean,如下所示:

@Value("classpath:my/path/MyJavaObject.xsd")
private Resource myJavaObjectSchema;

@Bean
@Qualifier("myMarshaller")
public Jaxb2Marshaller myMarshaller() {
   final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
   marshaller.setSchemas(myJavaObjectSchema);
   marshaller.setClassesToBeBound(MyJavaObject.class, JAXBElement.class);
   marshaller.setCheckForXmlRootElement(false);
   return marshaller;
}

所以我的问题是是什么导致了如此大的性能影响,或者我们如何找到问题所在。 2 磨机和 20 秒之间的差异是巨大的,当有效载荷结构相同时,为什么会出现这样的差异。有什么需要注意的地方或者有办法解决吗?此外,如果最坏的情况发生,是否有更好的 JAXB 替代方案。我们还使用 JAXB 进行模式验证,这是连接我们系统以符合行业标准的重要对象。

我们的 JAXB 类是 spring-oxm-5.3.27.jar 的一部分,后者将使用

javax.xml.bind:jaxb-api:2.3.1

** 更新 ** 我将解析器更改为不再是 Spring bean,而是为每条未编组的消息创建一个新的编组器实例,并且性能下降得更多:

parse 'Time taken to parse my request: *, client reference id: *' AS duration, clientReferenceId
| filter @message like 'Time taken to parse my request:'
| stats avg(duration)
Showing 1 of 9,831 records matched
12650.4609

parse 'Time taken to parse my request: *, client reference id: *' AS duration, clientReferenceId
| filter @message like 'Time taken to parse my request:'
| sort duration asc
  duration    clientReferenceId
1       16    OHaRPFh7Z2USRpfveFfB7NE1OEdU
2       16    3Xo1n6nZsrBtfROsRlh3N2rZHKK4

parse 'Time taken to parse my request: *, client reference id: *' AS duration, clientReferenceId
| filter @message like 'Time taken to parse my request:'
| sort duration desc
  duration    clientReferenceId
1   124585    Oj8L3Vt9dzDuWBb4wXv7yaUiv
2   120226    c972mxd544fjXqXIDp3DdPLP9
java spring-boot jaxb
1个回答
1
投票

我们做了类似的观察:我们在启用模式验证的情况下向 JAXB 抛出的线程越多,它的性能就越差。在我们的例子中,锁争用在探查器(如 VisualVM)的线程视图中清晰可见,我们能够将其追踪到每次编组/解组时调用的

synchronized
方法
com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory.getInstance()
。我们将此作为 bug 报告给 OpenJDK

请注意,Xerces2 库(JDK 的 XML 解析器/验证器实现源自于此)已于 2007 年解决了此问题(!)。您可以尝试使用它(只需添加依赖项,ServiceLoader 机制会自动拾取它) - 在我们的例子中,它 100% 解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.