Заметки инженера

Go · инфраструктура · мелкие находки

Когда 100% CPU — это не нагрузка, а подсказка

15 апреля · 4 мин

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

Прогнал perf top — и почти всё время тратилось внутри стандартной библиотеки на сериализацию JSON. Переделали на easyjson c предгенерацией, профиль выровнялся, хвост latency упал вдвое.

Мораль простая: если что-то постоянно тормозит — посмотри, как именно работает нижний слой. Часто дело не там, куда сначала смотришь.

ulimit — самая недооценённая настройка

2 апреля · 3 мин

Маленький параметр, но ломает поведение надёжнее, чем большинство "оптимизаций". Особенно на сервисах, которые держат много одновременных подключений: дефолтный лимит открытых файловых дескрипторов в 1024 заканчивается на ровном месте, и сервис начинает выбрасывать понятную только при вскрытии ошибку too many open files.

Поднимаем через systemd-юнит: LimitNOFILE=65536. Две минуты работы, плюс к стабильности под пиками.

Nagle и TCP_NODELAY: маленький флажок, большая разница

23 марта · 2 мин

По умолчанию TCP собирает мелкие записи в один пакет — алгоритм Nagle. На пропускной способности это выигрыш, но для latency-чувствительных протоколов (RPC, интерактив) дополнительные 40 мс задержки никому не нужны.

Лечится либо выставлением TCP_NODELAY на сокете, либо встроенной опцией фреймворка. В gRPC, например, это по умолчанию. В более старых клиентах — нужно включать руками. Простое изменение, а хвост latency иногда падает на порядок.

Sysctl, который обычно забывают

11 марта · 2 мин

Дефолтный vm.dirty_ratio в Linux рассчитан на машины без SSD и без современной нагрузки. В результате при массовом write-bursts система набирает в памяти гигабайты грязных страниц, а потом разом пытается их сбросить — и латентность встаёт колом.

Поднимаем vm.dirty_background_ratio, уменьшаем vm.dirty_ratio. Три строки в /etc/sysctl.d/, плюс sysctl -p. Местами даёт заметный эффект на запись в БД и на I/O-heavy сервисы.

Маленький трюк с bash-скриптами

28 февраля · 1 мин

Если скрипт запускается по SSH и фоновый процесс там нужен на долгий срок — nohup и & иногда не спасают: сессия рвётся, дочерний процесс цепляется за неё и умирает. Надёжнее через systemd-run --unit=name.

Плюс автоматически появляется управление через systemctl, и логи пишутся в journal. Решение, которое стоит помнить.