tg-me.com/eshu_coding/195
Last Update:
Палантир. Часть 6. Out of memory kill. Моя борьба.
#палантир@eshu_coding
Основной сервер существенно мощнее сборщиков: 4гб оперативки, 2 ядра 2.2 ГГц. Крутятся там два компонента системы: база данных - postgresql и сервис-обертка на ней. Сервис принимает подключения по grpc, генерирует и отдаёт приказы и укладывает пришедшие данные в бд.
Как только вся система начала работать в штатном режиме, ещё на 2 Гб оперативки, у меня возникла проблема: в какой-то момент Линуксу перестает хватать памяти и он пишет следующее: Out of memory: kill process X or sacrifice child. И убивает процесс.
Добавил файл подкачки в 3 Гб, накинул оперативку до 4гб, понизил приоритет моих процессов для OOM киллера. Вроде проблема прошла.
Смотрю утром: Out of memory: kill process postgresql or sacrifice child.
К тому же сервер начал негодовать, что бд нету и отложил 25 Гб ругательных логов, продублированных и в системные логи убунты.
По логам восстановил произошедшее: все 4 сборщика наткнулись на жирные каналы с большим количеством объемных (по 2кб в среднем) постов.
База не успевала всё переварить, скопилась очередь в 2 млн сообщений (2 Гб оперативки), OOM грохнул базу и все сошло с ума. Добавил приказы сборщикам на торможение: если в очереди на запись больше 100 тыс постов - сборщики получают команды поспать 10 секунд пока ситуация не разрешится. Также снизил лимит размера кэша у Постгреса с 1Гб до 500 мб. Запустил.
Утром: Out of memory: kill process postgresql or sacrifice child.
Покурил мануалы по постгресу, покрутил настройки, снизил лимит сна до 60 тыс сообщений.
На следующее утро: Out of memory: kill process postgresql or sacrifice child.
Проверил весь код на предмет утечки памяти. Нету. Наткнулся где-то на совет закрывать ненужные соединения с БД, решил попробовать.
Out of memory: kill process postgresql or sacrifice child.
Продолжил искать корень зла. Можно было бы конечно накинуть оперативки до 16 Гб, добавить пару ядер в цпу и перейти на SSD, но это во-первых не спортивно, во-вторых нет никакой гарантии, что проблема решится, а в-третьих - проект учебный. Люди когда-то жили без неограниченных ресурсов, значит и мне было бы неплохо научиться писать эффективный код.
И тут в какой-то момент я решил посмотреть, какой процесс сколько потребляет памяти в реальном времени.
Мой сервер-надстройка над базой - 500 мб-1.5 Гб по ситуации.
Постгрес основной процесс - 500 мб, как и прописал к конфиге. И ещё - 7 процессов по 250-300 мб. 3 - подключения моего сервера к БД: для записи сообщений, для записи юзеров и для записи чатов и каналов. 4 - подключения сборщиков, ведь именно на эту БД я повесил удаленное хранилище сессий, вот они и пользуются им.
Началась оптимизация: хранилище сессий уехало в другое место, все подключения сервера к БД я засунул в одно. А ещё добавил более адекватную тормозилку разогнавшихся сборщиков: при заходе за лимит (80 тыс сообщений в очереди на запись), сервер устанавливает паузу на прием следующего сообщения в 1 с. Когда очередь разгружается до 40 тысяч прием возобновляется в полном объеме.
Так и поборол я OOM Killer. Все крутится уже недели полторы без единого чиха.
BY Эшу быдлокодит
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/eshu_coding/195