Ухудшение производительности Apache Camel Route под нагрузкой - PullRequest
0 голосов
/ 25 января 2019

Я использую 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. Сначала я запустил тест на SoapUI MockService без задержки, а затем с задержкой 1100 мс.
Затем я настроил Apache Camel для направления запроса в службу SoapUI и повторил тесты.

JMeter -> SoapUI - задержка 0 мс
~ 1200 запросов в секунду; Средний запрос 25 мс; 0% ошибок

JMeter -> SoapUI - задержка 1100 мс
~ 100 запросов в секунду; Среднее количество запросов 1128 мс; 0% ошибок

JMeter -> Apache Camel -> SoapUI - задержка 0 мс
~ 420 запросов в секунду; Среднее значение запроса 285 мс; 0% ошибок

JMeter -> Apache Camel -> SoapUI - задержка 1100 мс
~ 8 запросов в секунду; Среднее значение запроса 14800 мс; 97,23% ошибок по таймауту

Время ожидания в Apache Camel установлено на 30 секунд.

Почему у Apache Camel такая низкая производительность в последнем случае и как я могу улучшить ее?

РЕДАКТИРОВАТЬ 1 :
Я создал репозиторий в GitHub, который содержит проект Apache Camel, фиктивный сервис SoapUI и тесты jmeter для легкого тестирования.

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

1 Ответ

0 голосов
/ 31 января 2019

Основная проблема

Такие проблемы всегда проблема ресурсов .Пока все компоненты имеют достаточно ресурсов и отвечают быстро, все в порядке.Как только один из них сталкивается с ограничением ресурсов, он становится медленным.

В сценарии JMeter-SoapUI преднамеренная задержка SoapUI равна , обработанной JMeter .Поскольку для ответа SoapUI требуется больше секунды, запросы JMeter остаются открытыми в течение этого времени.Если пул потоков JMeter для запросов исчерпан (все потоки ожидают ответа от SoapUI), он не может масштабироваться дальше.Исходя из ваших мер, размер пула потоков может быть 100.

Затем вы поставите верблюда в середину.При этом вы вводите новые пулы потоков .Должен быть один для приема запросов (CXF) и, вероятно, тот, который отправляет запросы (Camel HTTP).Теперь задержка SoapUI также должна обрабатываться этими пулами .Та же ситуация, но теперь пулы потоков компонента Camel являются ограничением.

Давайте предположим, что пул потоков для HTTP-запросов Camel по умолчанию равен 10.JMeter начинает отправлять запросы.Если JMeter отправляет новые запросы быстрее, чем SoapUI отвечает , 10 потоков для отправки HTTP-запросов в SoapUI очень быстро все заняты (ожидают SoapUI).

Поступают новые запросы JMeter, но новые HTTP-запросы к SoapUI невозможны до тех пор, пока один из потоков снова не освободится.Около 8 параллельных запросов (по вашим меркам) кажется разумным в этом случае.

Таким образом, очевидно, что если вы хотите обслуживать 100 запросов в секунду в подобном сценарии, вам нужно настроить все задействованные пулы потоков для обработки этого.И вы также должны точно настроить различные таймауты (CXF, Camel HTTP).

Ваш код

Одна вещь, которую я заметил в вашем коде, заключается в том, что вы используете Camel HTTP-компонент для своих конечных точек.Этот компонент использует HTTP-клиент Apache 3.x .

Если вы хотите использовать более современный клиент Apache HTTP , вы должны использовать Camel HTTP4компонент (4, потому что он использует Apache HTTP-клиент 4.x).Я не знаю, имеет ли это большое значение, но старая версия объявляется как «конец жизни» с годами.

Другое дело, тайм-ауты.Вы пишете, что устанавливаете время ожидания Camel на 30 секунд.Но это, вероятно, не тайм-аут CXF или HTTP-клиента Apache.У клиентов HTTP несколько тайм-аутов: для установления соединения может потребоваться слишком много времени, а для получения ответа может потребоваться слишком много времени.

...