Apache Camel Route 在负载下性能下降

Apache Camel Route performance degradation under load

我正在使用 Apache Camel 根据请求消息中的某个属性来路由 SOAP 请求。该消息与正则表达式匹配,如果找到匹配项,请求将被路由到 "calldestination1",如果没有,它将被路由到 "calldestination2".

我正在使用以下配置:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:cxf="http://camel.apache.org/schema/cxf"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd">

<!-- ... -->

<cxf:cxfEndpoint id="testEndpointTest"
    address="http://localhost:8080/testEndpoint"
    endpointName="s:testEndpoint_Port"
    serviceName="s:testEndpoint"
    wsdlURL="wsdl/testEndpoint.wsdl"
    xmlns:s="http://teste.com/testEndpoint"/>

<!-- ... -->

<camelContext xmlns="http://camel.apache.org/schema/spring">

    <endpoint id="calldestination1" uri="http://localhost:8080/destination1?bridgeEndpoint=true&amp;throwExceptionOnFailure=false"/>
    <endpoint id="calldestination2" uri="http://localhost:8080/destination2?bridgeEndpoint=true&amp;throwExceptionOnFailure=false"/>

    <route streamCache="true">
        <!--CXF consumer using MESSAGE format--> 
        <from uri="cxf:bean:testEndpointTest?dataFormat=MESSAGE"/>

        <choice>
            <when>
                <simple>${bodyAs(java.lang.String)} regex ${properties:router.regex}</simple>
                <to uri="calldestination1"/>
            </when>
            <otherwise>
                <to uri="calldestination2"/>
            </otherwise>
        </choice>

    </route>

</camelContext>

当运行 "calldestination2" 的目标服务器负载不足时,请求可能需要大约 1150 毫秒才能响应。 Apache Camel 似乎不能很好地处理这个问题。

为了复制这种行为,我将 SoapUI 与带有延迟的 SOAP MockService(OnRequest 脚本)和 jmeter 结合使用。 拳头 I 运行 针对 SoapUI MockService 的测试没有延迟,然后有 1100 毫秒的延迟。
然后我配置 Apache Camel 将请求路由到 SoapUI 服务并重复测试。

JMeter -> SoapUI - 0 毫秒延迟
每秒约 1200 个请求;平均 25ms 请求; 0% 错误

JMeter -> SoapUI - 1100 毫秒延迟
每秒约 100 个请求; 1128ms 平均请求; 0% 错误

JMeter -> Apache Camel -> SoapUI - 0 毫秒延迟
每秒约 420 个请求;平均 285 毫秒请求; 0% 错误

JMeter -> Apache Camel -> SoapUI - 1100 毫秒延迟
每秒约 8 个请求; 14800ms 平均请求; 97.23% 超时错误

Apache Camel 中的超时设置为 30 秒。

为什么 Apache Camel 在最后一个案例中性能如此低,我该如何改进它?

编辑 1:
我在 GitHub 中创建了一个存储库,其中包含 Apache Camel 项目、SoapUI 模拟服务和 jmeter 测试以便于测试。

https://github.com/jraimundo/apache-camel-route-tester

基本问题

此类问题始终是资源问题。只要所有组件都有足够的资源并快速响应,就可以了。一旦其中一个遇到资源限制,它就会变慢。

在 JMeter-SoapUI 场景中,SoapUI 的故意延迟由 JMeter 处理。因为 SoapUI 需要一秒以上的时间来响应,所以 JMeter 请求在这段时间内保持打开状态。如果用于请求的 JMeter 线程池耗尽(所有线程都在等待 SoapUI 的答复),它就无法进一步扩展。根据您的测量,线程池大小可能为 100。

然后你把骆驼放在中间。有了这个,您 引入了新的线程池 。必须有一个接收请求(CXF),可能还有一个发送请求(Camel HTTP)。现在 SoapUI 延迟也必须由这些池处理。同样的情况,但现在 Camel 组件的线程池是限制。

假设 Camel HTTP 请求的线程池默认为 10。 JMeter 开始发送请求。如果 JMeter 发送新请求的速度比 SoapUI 响应的速度快,那么向 SoapUI 发送 HTTP 请求的 10 个线程都非常快都忙(等待 SoapUI)。

JMeter 的新请求到达,但在其中一个线程再次空闲之前不可能向 SoapUI 发出新的 HTTP 请求。在这种情况下,大约 8 个并行请求(来自您的措施)似乎是合理的。

所以很明显,如果你想在这种情况下每秒处理 100 个请求,你需要调整所有涉及的线程池来处理这个问题。而且您还必须微调不同的超时(CXF、Camel HTTP)。

您的代码

我在您的代码中注意到的一点是您使用了 Camel HTTP component for your target endpoints. That component uses the Apache HTTP client 3.x.

如果您想使用更新的 Apache HTTP client, you must use the Camel HTTP4 component(4 因为它使用 Apache HTTP 客户端 4.x)。我不知道这是否有很大的不同,但多年来旧版本被声明为 "end of life"。

另一件事是超时。您写道,您将 Camel 超时设置为 30 秒。但这可能不是 CXF 或 Apache HTTP 客户端的超时。 HTTP 客户端有多个超时:建立连接可能需要很长时间,接收响应也可能需要很长时间。