Koha периодически вылетает

Материал из rrv-wiki
Перейти к навигации Перейти к поиску


OOM в Koha из-за поискового робота

Симптомы

Служба koha-common.service периодически останавливается с сообщениями:

A process of this unit has been killed by the OOM killer
Failed with result 'oom-kill'

Причина — исчерпание оперативной памяти. В рассматриваемом случае отдельные процессы Plack/Starman разрастались до 7–9 ГиБ, а два процесса вместе занимали почти всю доступную RAM.

Быстрая диагностика

Найти события OOM во всех доступных журналах:

journalctl --no-pager |
grep -Ei 'out of memory|oom-kill|oom_reaper|killed process|memory cgroup|systemd-oomd'

Ключевая строка:

Out of memory: Killed process ... anon-rss:...

Параметр anon-rss показывает фактический объём памяти, который занимал убитый процесс.

Посмотреть текущие процессы Koha:

ps -eo pid,ppid,lstart,etime,rss,vsz,%mem,%cpu,stat,cmd --sort=-rss |
grep -E '[s]tarman|[/]usr/share/koha'

Проверить ограничения systemd:

systemctl show koha-common.service \
   -p MemoryCurrent \
   -p MemoryHigh \
   -p MemoryMax \
   -p MemorySwapMax \
   -p OOMPolicy

Если MemoryMax=infinity, причиной является не лимит службы, а глобальная нехватка памяти.

Установленная причина

В журнале Plack непосредственно перед OOM обнаружено большое количество запросов:

GET /opac/opac-search.pl?...
User-Agent: GPTBot

Робот примерно каждую секунду открывал новые сочетания поисковых фильтров:

  • авторы и тематические рубрики;
  • типы и категории документов;
  • доступность;
  • повторяющиеся и вложенные фильтры;
  • RSS-представления результатов.

Это создавало практически бесконечное пространство поисковых ссылок. Обработка сложных запросов увеличивала RSS процессов Starman. Память не всегда сразу возвращалась системе, и worker-процессы постепенно разрастались до нескольких гигабайт.

Параметр Starman:

--max-requests 50

не полностью защищает от такой ситуации: worker перезапускается после завершения заданного числа запросов, но один длительный или тяжёлый запрос способен использовать большой объём памяти.

Имя процесса, который «вызвал» OOM, например mariadbd, zebrasrv или htop, не указывает на виновника. Это лишь процесс, который запросил дополнительную память, когда RAM уже закончилась. Виновный процесс указан в строке Killed process.

Принятое решение

В публичный HTTPS VirtualHost Apache добавлена блокировка GPTBot:

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} GPTBot [NC]
RewriteRule ^ - [F,L]

После изменения конфигурация проверена и применена:

apache2ctl configtest
systemctl reload apache2

Проверка блокировки:

curl -I -A 'GPTBot/1.4' \
'https://адрес-каталога/cgi-bin/koha/opac-search.pl?q=test'

Ожидаемый результат:

HTTP/1.1 403 Forbidden

Обычный браузер при этом не должен получать 403:

curl -I -A 'Mozilla/5.0' \
'https://адрес-каталога/cgi-bin/koha/opac-search.pl?q=test'

Настройка robots.txt

В каталоге статических файлов OPAC:

/usr/share/koha/opac/htdocs/robots.txt

создан файл:

User-agent: *
Disallow: /cgi-bin/koha/opac-search.pl
Disallow: /opac-search.pl
Disallow: /search

Он запрещает добросовестным роботам обход поисковых комбинаций, но оставляет доступными для индексации карточки изданий.

Проверка:

curl -sS https://адрес-каталога/robots.txt

robots.txt не является полноценной защитой: недобросовестный робот может его игнорировать. Поэтому для проблемного User-Agent дополнительно используется блокировка Apache.

Освобождение уже занятой памяти

После блокировки робота Plack перезапущен отдельно от остальных компонентов Koha:

koha-plack --restart имя_экземпляра

После перезапуска нормальный начальный размер каждого Starman worker-а составлял примерно 250 МиБ вместо 7–9 ГиБ.

Проверка:

ps -eo pid,ppid,etime,rss,vsz,%mem,cmd --sort=-rss |
grep -E '[s]tarman'

Дополнительная защита Koha

В современных пакетах Koha предусмотрена встроенная antibot-защита:

/etc/koha/apache-shared-opac-antibot.conf

Она может выдавать JavaScript-проверку анонимным посетителям тяжёлых страниц OPAC. Включать её следует осознанно: защита может помешать поисковым системам индексировать карточки каталога.

Мониторинг

Для контроля повторения проблемы подготовлен скрипт, который:

  • раз в минуту записывает суммарный RSS процессов Koha;
  • фиксирует крупнейший процесс;
  • контролирует доступную RAM и swap;
  • при превышении порога сохраняет процессы, cgroup, последние запросы Plack и сообщения ядра;
  • создаёт диагностические снимки не чаще одного раза в 30 минут.

Рекомендуемые пороги для сервера с 16 ГиБ RAM:

Один процесс Koha: 1 ГиБ
Все процессы Koha суммарно: 4 ГиБ

После внедрения блокировки новые запросы GPTBot перестали доходить до Plack, а память Starman стабилизировалась примерно на уровне 250–300 МиБ на worker.