Падение производительности Apache Camel Route под нагрузкой

Я использую 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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
2 349
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

В сценарии 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).

Ваш код

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

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

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

Я обновился до HTTP4 и получил явное улучшение производительности. Я могу использовать опцию «connectionsPerRoute» для дальнейшего увеличения параллелизма. Спасибо.

Raimundo 04.02.2019 17:26

Другие вопросы по теме