Der CollabDocdenburg: Постмортем одного инцидента в Fibery

Michael Dubakov
5 min readApr 29, 2021

DISCLAIMER: Текст написан инженерами команды Fibery (в основном Володей) в назидание молодым поколениям и как памятник сложности современной разработки программного обеспечения.

В тексте присутствует большое количество специальной и нецензурной лексики, поэтому читать рекомендуется инженерам, познавшим даунтайм в продакшене.

ЭТО ВОВА В ЧЕТВЕРГ

Действующие лица:

  • Коллаб — сервис коллаборативных документов в Fibery
  • Вова — разработчик Коллаба
  • Андрей — друг Вовы (тоже разработчик, но ядра)
  • Балансер — неизвестно как устроенный кусок чего-то

БЕСПЕЧНЫЙ ВТОРНИК

27 апреля (вторник) коллаб начал рестартовать по памяти.

Илья поднял лимит и оповестил о проблеме.

Вова посмотрел на график коллаба и подумал, что выросла нагрузка — вот и память подросла.

Решил понаблюдать за сервисом с поднятым лимитом (и лицом).

Память потиху росла, но до 2 гигов выставленного лимита ещё, казалось, было время подумать…

ПЫЛАЮЩАЯ СРЕДА

Пиздец наступил без привета в 16:48 среды.

Коллаб начал рестартовать, не доходя до лимита памяти в 2Gb.

Сам node процесс больше не мог выделять память. Стало очевидно, что утечка всё же есть.

После каждого рестарта — память опять забивалась в течение 30–40 минут. На графиках нагрузки коллаба это выглядело как фатальные пиковые нагрузки по миллиону записей.

Причём коллаб с ними справлялся, но вылетал по памяти:

Выяснились следующие проблемы:

  • в балансере коллаба застряло порядка 1.5 миллиона записей
  • очистка обработанных записей в базе балансера занимает порядка минуты на батч из 100

Попытались снизить нагрузку на балансер, подкрутив настройки коллаба, но это не дало результата.

В 1:26 ночи четверг Андрей делает ход конём — VACUUM на таблице балансера

После вакуума балансер пришёл в себя.

Вова всмотрелся в код балансера и нашёл, что он имеет кэш, в который выгружаются сообщения из базы балансера на каждый рестарт. По дефолту размер кэша ничем не ограничен, поэтому на каждый рестарт он всасывал ВСЕ 1.3 миллиона сообщений и отдавал их в обработку коллабу, который послушно выщемливал из них бэкрефы, нотификации и т.д. с достаточно приличной скоростью, НО…

…кэш наполнялся… сервис падал по памяти… после рестарта всё начиналось сначала.

Такое поведение оказалось неожиданностью. ОЖИДАЛОСЬ, что балансер не берёт в работу следующие записи, пока не убедится, что обработанные вычищены.

В 2:28 ночи Вова растыкал настройки кэша и вернул лимит памяти контейнеру.

ЧУДОВИЩНЫЙ ЧЕТВЕРГ

Кастомеры начали жаловаться на дубликаты нотификаций и бэкрефов.

…тут до Вовы дошло, что ночью было только начало…

Также обратили внимание на пищащий алерт в очереди сервиса collab-2-fibery (далее C2F). До него не доходили руки ранее, т.к. тушили пожар в коллабе.

Очередь стала активно расти с 16–30 среды (совпадает по времени с огнём в коллабе):

Начальная проблема была в том, что один аккаунт xxx.fibery.io блочил очередь ошибкой 504 и сервис пытался безуспешно её решить ретраями.

Впилили явное исключение этого аккаунта, чтобы обработка пошла дальше. В логе ядра обнаружили соот-е ошибки о превышении времени выполнения запроса лимита в 60 сек.

Очередь начала медленно разгребаться, но по балансу всё равно продолжила расти.

Лёша добавил сенсоров.

Андрей всмотрелся в потенциальные проблемные запросы к ядру от C2F.

Андрей нашёл запрос за выгребанием ACL’ов, который стал жутко втупливать.

Андрей применил оптимизацию, понятную только разработчикам ядра. Оптимизация заключалась в НЕприменении формы запроса, которая приводит к неэффективному плану выполнения запроса и выполняется вечность. На это есть баг в ядре старый как Андрей. Андрей всё это знал и по-дедовски смекнул что к чему, потому что наелся подобного говна год назад в ядре.

С 3 попытки около 14:00 учередь ушла в пикЕ.

Все выдохнули и поменяли памперсы.

Причины пиздеца

  • накопление коллабом + балансером миллиона сообщений для разгребания. Почему так произошло непонятно. По логам видно, что в 3:30 ночи 27 апреля база балансера встала колом. Причём произошло это скачкообразно и по логам не связано с пиками нагрузки на коллаб сервис. Нужна экспертиза Ильи.. возможно инфраструктурная проблема, сбой автовакуума.
  • пухнущая очередь у C2F. Тут гипотеза следующая — в результате, секуризации fibery типов (fibery/view, …) кол-во ентитей типа fibery/access-group возросло примерно на 100. Это могло повлиять на окончательное проседание производительности запроса за доступом в ядро, выполняющимся в обработчике сообщений C2F, что окончательно убило скорость разгребания сообщений.

Проблемы

  • дублирующиеся нотификации. Сделать ничего уже нельзя.. репутационный импакт. Надеемся на дипломатические навыки Полины и Миши.
  • дублирующиеся бэкрефы — Вова сделает реиндексацию, должны исчезнуть. Пока дипломатично обещаем жалующимся.
  • баг в ядре, приводящий к неэффективному плану выполнения запроса, отправленного C2F. В итоге, запрос обваливался по таймауту, и C2F наивно начинал его ретраить с надеждой на опционы лучшее будущее. В результате, забуксовала логика обработки сообщений от всех акков.

Action Points

  • изучить гарантии, предоставляемые балансером!!!
  • дублирующиеся нотификации → идемпотентность операции отправки нотификации
  • дублирующиеся бэкрефы → миграция-убийца дубликатов + upsert бэкрефа?
  • пофиксить баг в ядре + не ретраить в C2F на таймаут + очертить логику работы в C2F с ошибками для сужения их импакта

--

--

Michael Dubakov

Fibery founder https://fibery.io. I write about systems, software development and products.