История ужасов с элементами юмора: индексы, убийства, секс и JIRA

15 Авг, 2018
Aleks Yenin

Опубликовано Aleks Yenin

Это всё началось с одного из инстансов JIRA, который разросся до таких масштабов, что ресурсов, выделенных при первоначальной оценке мощности, стало критически не хватать.

Благо, сервер виртуальный, и добавить еще 5 гигабайт оперативной памяти не составило каких-либо трудностей. Но все не могло просто пройти так легко.

После перезагрузки сервера мы обнаружили, что в Jira перестали отображаться все тикеты, они были убиты, просто исчезли. При этом, проекты и пользователи были видны, логин работал нормально. Сразу поняли, что проблемы с индексацией. Для индексации очень важны следующие компоненты системы: процессор, ОЗУ, база данных, файловая система, где хранятся индексы. Любой из этих компонентов может привести к тому, что весь процесс будет значительно замедлен или вообще нарушен. После беглого расследования выяснилось, что сервер, база данных и жесткий диск в порядке. Однако, папка, в которой должны храниться файлы индексации, было пустой. Мы задались закономерным вопросом «Как так?».

Как оказалось, исторически было принято решение хранить папку с индексами ($HOME/caches/) целиком в оперативной памяти (на рамдиске). А так как сервер нужно было перезагрузить после увеличения ресурсов, то файлы индексов были удалены.

Индексы в Jira делаются с помощью библиотеки Lucene от Apache. Основная концепция Lucene:

  •    Документ – поисковая единица, тикет в нашей ситуации. В одном индексе может содержаться от одного до нескольких документов.
  •    Поля – составляющие «Документа», обычно состоит из имени и значения. В нашем случае, это любое поле тикета.
  •    Поиск – инструмент для нахождения нужных “Документов” посредством “Запросов” по индексам. В Jira это Issue Search.
  •   Запросы – это такой мини язык, посредством которого мы запрашиваем у индексов нужные нам «Документы». Мы вводим значение, задаем какое «Поле» его содержит и Lucene находит его. Также существуют операторы «AND», «OR», «NOT», которые сужают и конкретизируют поиск. Для Jira, как известно, это JQL.

JIRA создает индексы не только для тикетов. Также отдельными «Документами» являются: комментарии, истории изменения тикетов и рабочее время. В любом случае для JIRA в качестве источника истины является база данных и создает она индексы посредством запросов SQL.

Когда тикет создается или изменяется в JIRA, создается документ Lucene, который содержит поля этого тикета, а также некоторые дополнительные расчетные данные, которые полезны для поиска. Всякий раз, когда JIRA индексирует тикет, она передает этот тикет и связанный с ней документ Lucene в плагин, который может модифицировать документ Lucene как ему хочется, прежде чем возвращать имена любых добавленных им полей. Затем этот документ Lucene добавляется в индекс Lucene, заменяя любой предыдущий документ для этого тикета в индексе.

Итак, нам нужно было срочно провести индексацию всей JIRA. Есть несколько вариантов индексации: фоновая индексация и индексация с блокировкой.

Фоновая индексация – это индексация, при которой берется уже существующие индексы и Jira находит в них отличие от того, что мы имеем в реальности. Происходит инкрементация — все различия добавляются в дополнительные файлы с новыми индексами со специальной пометкой. Использует только один поток в процессоре, поэтому проходит очень медленно, но не блокирует работу Jira. Также пагубно влияет на сервер так как приводит к фрагментации диска.

Индексация с блокировкой – это индексация, при которой блокируется доступ к Jira и удаляются все индексы, после чего создается полный набор индексов. И используется все потоки, выделенные для Jira.

Было очевидно, что нам нужен был второй вариант.

Как известно, индексация Lucene потребляет огромное количество ресурсов, а на чтение данных приходится около 80% этих запросов. Это сильно зависит от того, какие плагины установлены и как они хранят и индексируют данные.

Jira при проведении индексации производит активные SQL запросы к базе и достает всю интересующую нас информации, по которой впоследствии мы можем проводить поиск. Затем обрабатывает тикеты один за другим, преобразовывая их в «Документы» с «Полями», потребляя относительно мало оперативной памяти. Тем самым и получаются индексы.

Обычно, индексы хранятся на жестком диске и постоянно реструктуризируется по мере добавления и удаления «Документов». Быстрота поиска достигается тем, что в поисковом запросе каждое поле занимает всего лишь 1 байт ОЗУ. А удаление документа из индекса всего-то 1 бит.

Мы запустили индексацию с блокировкой и к нашему удивлению, или даже огорчению, 1% индексации был выполнен только через полтора часа.  И тут начался SEX!

Началось расследование: «Что же мешает нашей Jira выполнить индексацию быстро?»

Как оказалось, разработчики Jira не предполагали насколько может разрастись отдельный сервер и предоставили на индексацию только 5 потоков по умолчанию. И после нескольких манипуляций с настройками и перезапуска сервера мы запустили индексацию заново. Теперь уж Jira было где разгуляться, и она потребляла до 90% процессорного времени. Но даже этого было недостаточно, что-то все равно была большая конкуренция за ресурсы. Стало ясно, что это «что-то» находится в самой Jira. А что еще может потреблять ресурсы в Jira, когда она заблокирована от пользователей. Правильный ответ плагины. И самый прожорливый из них всеми любимый ScriptRunner.

Было принято решение отключить для начала ScriptRunner, а потом и другие плагины и освободить нашу Jira от всех лишних задач, так как на данный момент у нас была одна самая важная задача – вернуть Jira работоспособность.

Итак, индексация запущена, пальцы скрещены, все затаили дыхание и наблюдали за полосой прогресса. В HipChate  прогремели радостные возгласы и всеобщее ликование. Проценты шли один за другим. Через час все было кончено. Осталось только запустить обратно плагины и смахнуть холодный пот с наших лбов, конечно выполним диагностику работоспособности ScriptRunnerа.

А всего на всего надо было сделать бекап индексов на жесткий диск и восстановить их в обычную папку после рестарта сервера и до старта JIRA! Информация об этом инциденте была добавлена в базу знаний и в будущем мы избежим подобных случаев.

Поделиться:

Напишите нам

Мы всегда рады Вам помочь