【问题标题】:JAXB.marshal blocking webservice callJAXB.marshal 阻塞 web 服务调用
【发布时间】:2017-09-01 17:58:47
【问题描述】:

我正在使用 Spring WebserviceTemplate 对服务进行 SOAP 调用。我进行了性能测试以查看它在负载下的表现。我还有一个拦截器,可以将传入请求中的标头参数复制到我正在调用的服务中。

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor {

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        JAXB.marshal(getRequestHeader(), result);
        return true;
    }

当我运行性能测试时,我看到下面的语句阻塞了 4-5 秒

JAXB.marshal(getRequestHeader(), result);

这可能是阻塞的原因吗?

【问题讨论】:

  • 你看到JAXB类的javadoc了吗?它说:“一般来说,性能不一定是最佳的。预计需要编写性能关键代码的人将直接使用 JAXB API 的其余部分。
  • 谢谢,但它通常会在 100 毫秒内响应。我仅在尝试加载测试时才看到此问题。这是否与我们同步导致了这种延迟?当我打开类时,我看到方法是静态但不同步
  • 创建JAXBContext 通常是最耗时的部分。其余的编组/解组并没有那么慢。
  • 由于最耗时的操作是创建JAXBContext,您是否尝试通过在创建拦截器后创建JAXBContext(在@PostConstruct 方法中)然后尝试更改代码编组/解组 SOAP 消息?也许在您的性能测试中,当有多个线程尝试创建上下文时,它们会产生瓶颈
  • 您只需要一个JAXBContext - @PunterVicky。它是线程安全的,正如人们所说的那样 - 实例化非常昂贵。

标签: java spring spring-boot jaxb webservicetemplate


【解决方案1】:

JAXB 实用程序类将在第一次调用时创建 JAXBContext(昂贵的操作)。它将被弱缓存,这意味着如果内存不足,上下文可能会被回收,并在接下来的调用中重新创建。你真的应该创建你的上下文并明确地保留它。这样的事情(正如其他人在 cmets 中已经建议的那样)应该可以解决您的问题:

@Component
public class HeaderPropagationInterceptor implements ClientInterceptor
{
    private JAXBContext jaxbContext;

    @PostConstruct
    public void createJaxbContext() {
        try {
            jaxbContext = JAXBContext.newInstance(RequestHeader.class);
        }
        catch(JAXBException e) {
            throw new IllegalStateException("Unable to create JAXBContext.", e);
        }
    }

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        SoapMessage request = (SoapMessage) messageContext.getRequest();
        Result result = request.getSoapHeader().getResult();
        jaxbContext.createMarshaller().marshal(getRequestHeader(), result);
        return true;
    }
}

您必须将RequestHeader.class 替换为您的代码使用的实际类。如果需要进一步提高性能,也可以使用线程本地来重用编组器,但您可能应该进行进一步的分析以验证这确实是一个瓶颈。祝你的项目好运!

【讨论】:

  • 我认为在 @PostConstruct 方法上不允许使用 throws JAXBException。请参阅thisthis 问题。因此,您需要删除 throws 子句,而是在您的方法中添加一些 try/catch 逻辑。
  • @ThomasFritsch 是的,你是对的。我将更新示例!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 2022-12-09
  • 2013-05-14
  • 1970-01-01
  • 2016-04-11
相关资源
最近更新 更多