В настоящей статье расскажу историю о том, как можно столкнуться с довольно простой проблемой на больших инсталляциях продуктов компании Atlassian, в частности на Jira. 

Методы анализа и поиска узких мест:

  1. статистика

  2. сэмплирование

  3. профилирование и трассировка

В этой статье мы разберем трассировку запросов, которая показывает практически весь отрезок запроса, а именно от начала запроса с браузера клиента до перехода к обратному прокси, если он существует, к серверу приложений и от него до кэшей, поисковых индексов Lucene, СУБД. 

Важный момент — сложно провести анализ системы со стороны заказчика, так как с их стороны были жесткие требования по использованию инструментов, которые перечислены в требованиях.

Требования 

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

Поэтому критерии выбора инструмента были следующими: 

  • бесплатный;

  • установка на собственной инфраструктуре (On-Premise);

  • открытый исходный код;

  • возможность интеграции с Elasticsearch (Opendistro);

  • совместимость с JVM (поскольку Atlassian написан в основном, на Java), или как javaagent;

  • возможность связки запроса HTTP c SQL-запросы;

  • наличие графиков в перцентилях;

Для меня последний пункт важен, поскольку он помогает выявить отправную точку, чтобы не заниматься последствиями. На рисунке ниже видно, что проблема фактически началась в 12 часов ночи, а не спустя 1 час. В случае отсутствия деления на процентили легко можно потратить много времени на устранение симптомов и только потом разобраться с причиной. Конечно, случаи бывают разные. 

график
график

В качестве отправной точки использовался сайт https://openapm.io/landscape, который собрал практически все актуальные APM-инструменты. После проведения сравнительного анализа мы остановили выбор на инструменте Glowroot, который удовлетворял всем критериям.

Установка 

Установка приложения довольно простая на агентах, и в данной статье показана схема работы со встроенным коллектором, но для промышленных инсталляций используется Cassandra (как представлено на диаграмме) со связкой с Elasticsearch.

  1. Скачиваем инсталлятор

wget -c https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip

2. Для проверки создаем директорию mkdir -p /jira/glowroot/tmp, чтобы владелец процесса приложения Jira мог писать в эту же директорию, и устанавливаем права на владение для простоты, но рекомендуется просто выдать возможность записи владельцу процесса Jira

chown -R jira: /jira/home/glowroot

3. Устанавливаем дополнительно аргумент в setenv.sh в инсталляционной директории jira, в нашем случае это /jira/current/bin. По умолчанию, Атлассиан использует директорию /opt/atlassian/jira/bin в файле добавляем следующую строку:

JVM_SUPPORT_RECOMMENDED_ARGS="-javaagent:/jira/glowroot/glowroot.jar ${JVM_SUPPORT_RECOMMENDED_ARGS}"

4.После перезапускаем приложение: 

systemctl restart jira

И мониторим на наличие ошибок посредством команды:

tail -f {jira_installation_directory}/logs/catalina.out 

Так как по умолчанию биндится адрес 127.0.0.1, то идем в директорию в glowroot и смотрим, что появились файлы такие, как admin.json. В ней можете поменять bindAddress на 0.0.0.0 или на нужный вам. В моем случае я добавлю contextPath - /glowroot

И после на reverse proxy (в данном случае nginx), устанавливаем:

location /glowroot {                 
		proxy_pass http://127.0.0.1:4000; 
}

Дополнительно можете посмотреть на приложенную документацию Agent-Installation-(with-Embedded-Collector)

Как результат, по нашему адресу jira.example.com/glowroot видит транзакции.

Первичные анализы

Спустя некоторое время графики и сэмплы пополняются, как следствие инженер по исследованию узких мест начинает создавать множество задач. 

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

Чем больше система, тем неожиданнее сюрпризы

Посредством glowroot было обнаружено, что при каждом изменении задачи в проекте с количеством пользователей более 30000, при проверке прав создавались временные таблицы на стороны СУБД. Ниже представлен trace, который это демонстрирует.

Как результат, создаются временные таблицы на стороне СУБД PostgreSQL, а на кластере PostgreSQL эта активность сильно влияет на производительность в связи с высоким показателем IOPS.

glowroot в деле
glowroot в деле

Возникал вопрос — почему кэширование на стороне приложения Jira не отрабатывало, ведь согласно thread dump информации показывает, что существует кэширование объектов.

Согласно stacktrace из трассированого запроса был видно, что реализация кэширования выполнена абсолютно удобно.

кусок трейса
кусок трейса

При изучении stacktrace было обнаружено, что метод createTemporaryTablesIfNeeded влиял на эту деградацию по производительности. 

И нижеприведенный пулл реквест изменил поведение приложения,  https://bitbucket.org/atlassian/entity-engine/pull-requests/32/stable-issue-stable-issue-raid-438-in/diff, как следствие мы столкнулись с этой проблемой на большой инсталляции.

так и нашли ограничения
так и нашли ограничения

Причиной изменения было ограничение неправильно настроенных проектов и ограничение действительно больших проектов. Так что данное решение является довольно прагматичным решением в программной инженерии.

В качестве вывода

Как мы видим из примера изменения в entity engine, вендор также беспокоится за продукт и с удовольствием принимает запросы на улучшение, если это относится к его компоненте. 

А решили мы свои проблемы пересборкой компоненты под наши реалии, не дожидаясь правильного и официального фикса. 

Фактически у нас были следующие варианты по устранению поведения приложения для большого количества пользователей:

  • Изменить константу и пересобрать компонент

  • Изменить схему прав безопасности на уровне приложения и провести очистку и полное ревью

  • Переделать на unlogged таблицу cwd_users в PostgreSQL

Подскажите,сталкивались ли вы подобными ситуация и как решали? Особенно, интересны ситуации, связанные с поиском узких мест в системе посредством инструментов по анализу производительности? Как много времени потратили на установку, настройку инструментов и выявление проблем? 

Буду рад вашим вопросам, а также можно задавать Atlassian сообществе в Телеграм.

Хорошего дня, Гончик.

Ссылки