Причина задержки в веб-сервисе Axis2 - PullRequest
1 голос
/ 10 января 2012

У меня есть веб-служба Java SOAP, изначально разработанная в Axis 1, которая не соответствует моим требованиям к производительности.

Больше всего меня беспокоит запрос, который используется для добавления большого количества (миллионов строк) данных в базу данных. На стороне клиента я просто буду просматривать файлы и отправлять эти данные в мой веб-сервис. Каждая строка имеет три элемента, поэтому запрос выглядит примерно так:

<SOAP Envelope/Header/Body>
<AddData>
  <Data>
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
    <Age>42</Age>
  </Data>
</AddData>
</SOAP Envelope/Body>

Я нахожу следующие тенденции производительности:

  • Когда я делаю одну строку на запрос, я могу получить около 720 строк в минуту.
  • Когда я инкапсулирую несколько строк в один запрос, я могу получить до 2400 строк в минуту (100 строк на запрос).

К сожалению, эта производительность не будет соответствовать нашим требованиям, поскольку мы можем вставить сотни миллионов строк (при 2500 строк в минуту загрузка всех данных займет около 2 месяцев).

Итак, я изучал приложение, чтобы увидеть, где находится наше узкое место. Каждый запрос из 100 строк занимает около 2,5 секунд (я пробовал несколько разных серверов и получаю похожие результаты). Я нашел следующее:

  • Расходы на стороне клиента незначительны (из-за мониторинга производительности моего собственного клиента и использования SOAP UI)
  • Активность базы данных составляет всего около 10% (0,2 с) от общего времени, поэтому кэширование в Hibernate и т. Д. Не сильно поможет.
  • Сетевые издержки незначительны (<1ms время пинга от клиента к серверу, пропускная способность> 10 МБ / с при каждой отправке запроса <20 КБ). </li>

Таким образом, это оставляет около 2 секунд неучтенными. Единственная другая часть этой головоломки, на которую я могу указать пальцем, - это издержки десериализации входящих запросов на стороне сервера. Я заметил, что Axis 2 требует улучшения скорости в этой области, поэтому я перенес эту функцию через веб-сервис Axis 2, но не получил нужное мне ускорение (общее время на запрос увеличилось примерно на 10%).

Я недооцениваю количество времени, необходимое для десериализации 100 элементов, описанных выше? Я не могу представить, что эта десериализация может занять около 2 секунд.

Что я могу сделать, чтобы оптимизировать производительность этого веб-приложения и сократить эти 2-секундные накладные расходы?

Заранее спасибо!

========= На следующий день .... =========== Сюжет утолщается ...

По рекомендации @millhouse я исследовал запросы на одну строку еще на одном производственном сервере. Я обнаружил, что они могут быть достаточно быстрыми на хорошем оборудовании. Поэтому я попытался добавить 1000 строк, используя приращения в диапазоне от 1 (1000 отдельных запросов) до 1000 (один запрос).

  • 1 строка / Запрос - 14,5 секунд
  • 3 / req - 5,8 с
  • 5 / req - 4,5 с
  • 6 / req - 4,2 с
  • 7 / req - 287 с
  • 25 / req - 83 с
  • 100 / req - 22,4 с
  • 1000 / req - 4,4 с

Как видите, дополнительные 2 секунды задерживаются на 7 строк на запрос (примерно 2 дополнительные секунды на запрос по сравнению с 6 строками на запрос). Я могу воспроизвести это последовательно. Все большее количество запросов имели одинаковые накладные расходы, но это стало менее заметно при вставке 1000 строк на запрос. Время базы данных росло линейно и все еще было незначительным по сравнению с общим временем запроса.

Итак, я обнаружил, что я получаю наилучшую производительность, используя либо 6 строк на запрос, либо тысячи строк на запрос.

Есть ли какая-либо причина, по которой производительность 7 будет ниже, чем 6 строк на запрос? Машина имеет 8 ядер, и у нас есть 10 подключений в пуле сеансов (т.е. я понятия не имею, откуда берется порог 6).

1 Ответ

1 голос
/ 10 января 2012

Я использовал Axis2 для аналогичной работы около 5 лет назад, но боюсь, что не смогу предложить какую-то настоящую «волшебную пулю», которая сделает его лучше. Я вспоминаю, что наш сервис работал со скоростью сотен в секунду , а не секунд-на-сотню .

Я бы порекомендовал либо профилировать вашу обработку запросов, либо просто добавить обильное количество журналирования (возможно, используя одну из многочисленных реализаций секундомера, чтобы дать подробные сведения о времени) и посмотреть, что использует время. Действительно ли запрос занимает 2 секунды, чтобы пройти уровень Axis к вашему коду, или он просто накапливается через множество мелких вещей?

Если обработка для отдельного запроса в отдельности выполняется быстро, но после загрузки службы все застопорилось, изучите параметры потоков сервера приложений. Кажется, я вспоминаю о необходимости разбить свою обработку на синхронные и асинхронные части (т. Е. Синхронная часть, выполняющая необходимый минимум для возврата подходящего ответа клиенту, и тяжелая работа, выполняемая в потоке из пула), но это может не подходит для вашей ситуации.

Также убедитесь, что создание нового объекта User (или чего бы то ни было) не делает ничего слишком дорогого (например, получение нового идентификатора) из службы, которая оборачивает DAO, которая сталкивается с медленным сервером базы данных , который запускает плохо написанную хранимую процедуру, которая блокирует всю таблицу ;-))

...