Как стать автором
Обновить
68.97
Voximplant
Облачная платформа голосовой и видеотелефонии

Перевод: как gitLab использует unicorn и unicorn-worker-killer

Время на прочтение 3 мин
Количество просмотров 9.6K
Автор оригинала: Jacob Vosmaer
Предлагаю вашему вниманию перевод небольшой статьи, в которой инженеры GitLab рассказывают как их приложение работает на Unicorn и что они делают с памятью, которая течет. Эту статью можно рассматривать как упрощенную версию уже переведенной на хабре статьи другого автора.

Unicorn


Для обработки HTTP запросов от git и пользователей GitLab использует Unicorn, Ruby сервер с prefork. Unicorn — это демон, написанный на Ruby и C, который может загружать и выполнять Ruby on Rails приложение, в нашем случае — GitLab Community Edition или GitLab Enterprise Edition.

Unicorn имеет мультипроцессную архитектуру для поддержки многоядерных систем (процессы могут выполняться параллельно на разных ядрах) и для отказоустойчивости (аварийно завершившийся процесс не приводит к завершению GitLab). При запуске основной процесс Unicorn загружает в память Ruby и Gitlab, после чего запускает некоторое количество рабочих процессов, которые наследуют этот «начальный» слепок памяти. Основной процесс Unicorn не обрабатывает входящие запросы — это делают рабочие процессы. Сетевой стек операционной системы получает входящие подключения и распределяет их по рабочим процессам.

В идеальном мире основной процесс один раз запускает пул рабочих процессов, которые затем обрабатывают входящие сетевые подключения до скончания веков. На практике рабочие процессы могут аварийно завершиться или же быть убиты по превышению времени ожидания. Если основной процесс Unicorn обнаруживает, что один из рабочих процессов обрабатывает запрос слишком долго, то он убивает этот процесс с помощью SIGKILL (kill -9). Вне зависимости от того, как завершился рабочий процесс, основной процесс заменит его на новый, который наследует все то же «начальное» состояние. Одна из особенностей Unicorn — возможность заменять дефектные рабочие процессы не обрывая сетевых подключений с запросами пользователей.

Пример таймаута рабочего процесса, который можно найти в unicorn_stderr.log. Идентификатор основного процесса 56227:

[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
[2015-06-05T10:58:08.708141 #62538]  INFO -- : worker=10 spawned pid=62538
[2015-06-05T10:58:08.708824 #62538]  INFO -- : worker=10 ready


Основные настройки Unicorn для работы с процессами — это количество процессов и таймаут, по истечении которого процесс будет завершен. Описание этих настроек можно посмотреть в этом разделе документации GitLab.

unicorn-worker-killer


В GitLab есть утечки памяти. Эти утечки проявляются в долго работающих процессах, в частности — в рабочих процессах, создаваемых Unicorn (при этом в основном процессе Unicorn таких утечек нет, так как он не обрабатывает запросов).

Для борьбы с этими утечками памяти GitLab использует unicorn-worker-killer, который модифицирует рабочие процессы Unicorn чтобы они проверяли использование памяти через каждые 16 запросов. Если объем используемой памяти рабочего процесса превышает установленный лимит, то процесс завершается и основной процесс Unicorn автоматически заменяет его на новый.

На самом деле это неплохой способ борьбы с утечками памяти, так как дизайн Unicorn позволяет не терять запрос пользователя при завершении рабочего процесса. Более того, unicorn-worker-killer завершает процесс между обработкой запросов, так что это никак не отражается на работе с ними.

Вот так в файле unicorn_stderr.log выглядит рестарт рабочего процесса по причине утечки памяти. Как можно видеть, процесс с идентификатором 125918 после самоанализа принимает решение завершиться. Пороговое значение памяти при этом составляет 254802235 байт, то есть порядка 250 мегабайт. GitLab использует в качестве порогового значения случайное число в диапазоне от 200 до 250 мегабайт. Основной процесс GitLab с идентификатором 117565 затем создает новый рабочий процесс с идентификатором 127549:

[2015-06-05T12:07:41.828374 #125918]  WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
[2015-06-05T12:07:41.828472 #125918]  WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
[2015-06-05T12:07:42.025916 #117565]  INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
[2015-06-05T12:07:42.034527 #127549]  INFO -- : worker=4 spawned pid=127549
[2015-06-05T12:07:42.035217 #127549]  INFO -- : worker=4 ready


Что еще бросается в глаза при изучении этого лога: рабочий процесс обработал всего 23 запроса, прежде чем завершиться из-за утечек памяти. На данный момент это является нормой для gitlab.com

Такой частый рестарт рабочих процессов на серверах GitLab может стать причиной беспокойства для сисадминов и devops, но на практике это чаще всего нормальное поведение.
Теги:
Хабы:
+14
Комментарии 15
Комментарии Комментарии 15

Публикации

Информация

Сайт
www.voximplant.com
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия