Короче, постом выше написал про то, как мы избввились от привязки сущностей к инстансам, сделав упрощенные распределенные локи
Все работало, показывало перфоманс, но ровно до вчерашнего дня...
Началось все с того, что не могли зареконектиться 5 контроллеров, посмотрели на их поведение, подумали: "Аномалии бывают" – через 2 часа таких контроллеров стало 40, через час их стало 300, а через еще полчаса 2000...
Причем они не просто "реконектились", они в абсолютно рандомном порядке получали и отдавали сообщений, время от времени возвращаясь в норму на пару минут и обратно в хаос
Хуже еще то, что во втором идентичном контуре (с меньшей нагрузкой) все абсолютно нормально
Ну ок, первое предположение неправильно работают локи, тестируем, все ок, дальше смотрим как привязываются сокеты, тут тоже все попротоколу, далее предполагаем, что проблема в БД, но и она в норме, потом думаем, что тупят сервисы, но event loop и memory в прекрасном состоянии
Тут мы случайно заметили, что сообщения уже на выходе от нас на контроллер имеют время на 5 минут раньше, чем реальное, поэтому он их отбрасывает, как слишком старые
Проверяем корректность времени кластера, все ок, проверяем ноду, все ок, проверяем железо, все ок
Решили, что поскольку мы не можем найти источник проблемы лучше сделать набор защитных механизмов (связанных с локами и таймстемпами), выкатить в прод и посмотреть
Что мы ни делали, результата не было
В итоге я принял решение переписать парсинг сообщений с распределенного лока на БД (чуйка подсказывала что проблема где-то здесь)
За час я написал очередь, пуллер, health checks, миграции и индексы, убрал весь старый код, выпустили и все абсолютно нормализовалось...
Все разошлись спать (а один уже уснул прям напротив монитора), но я решил все-таки попробовать понять что пошло не так
И тут мое внимание привлек 1 лог: сообщения на контроллер отправляются сразу с двух сервисов и сразу в 2 открытых TCP сокета....
Выяснилась поразительную вещь: контроллер в теории оказывается может не закрыть предыдущие соединения, но даже в этом случае запись в это соединение должно его закрывать, и оказалось, что где-то на уровне proxy / multiplexer / kubernetes / cloud / dns / провайдера просто происходит ДУБЛИРОВАНИЕ TCP СОКЕТА
То есть он не просто не закрывался (что является стандартным поведением), он еще мог принимать сообщения
Поэтому во время реконектов контроллеров, каждый контроллер успевал приконектиться к каждому сервису с TCP сокетами, оставив на каждом из них открытое соединение, которое вело в никуда
Когда мы запрашивали сообщения с сокет сервисов, он брал последнее присланное сообщение от контроллера и с вероятностью в 12% (1 из 8 инстансов) это было реально последнее сообщение из реально открытого сокета, но в 88% это было уже устаревшее сообщение из сокета, который просто не закрылся....
В новой же модели, мы достаем сообщения из БД, куда в кчу скидывают все контроллеры, а отправляем ответ на основании id сервиса, который последний принял сокет
Заключение: никогда не рассчитывайте, что TCP сокет закроется или вы как-то сможете проверить, что он реально закрыт
Как фикс этой ситуации мы просто делаем бродкаст события при переподключении, чтобы все инстансы убили у себя старое соединение по этому контроллеру
A
Arsen ИТ-К Arakelyan
2023-10-04 22:33
Бро, ты жив вообще?) Почти 22 проведенного сидя, в целом не звучит здорово) А ты еще и пиздец как много умственно заморачился-заебался судя по посту😂
🦾
🦾 IT-Качалка Давида Шекунца 💪
2023-10-04 22:35
P.S.
Из приятного: новая система коммуникации (через БД), во-первых, снизила время процессинга с динамических 1-10 секунд до константных 300 мс (накинули еще 1000 контроллеров сегодня и показатель не шелохнулся), во-вторых, снизилась нагрузка на сервисы на 50% и самое интересное, что в итоге нагрузку на БД упала на 30%
Ну и заодно мы сохранили sateless, получили дебагабилити, историю задач и код расрпделенного лока представляет из себя 5 функции с 6 SQL запросами
О том, как конкретно мы это сделали и как знание уровней изоляции и Optimistic / Pessimistic локов дало такой буст я расскажу в следующих постах
🦾
🦾 IT-Качалка Давида Шекунца 💪
2023-10-04 22:36
Аллилуя женщина была дома и она следила за тем, чтобы я не сдох от жажды / голода и не начал сраться под себя
A
Arsen ИТ-К Arakelyan
2023-10-04 22:55
Сразу вспомнил маму Картмана, которая приносила сыну не только пожрать, но и горшок чтобы он не отходя от компа сразу срал, чтобы не тратить ни минуты зря, во время легендарного квеста в WoW-е 🤣🤣🤣🤣❤️🔥🔥
🦾
🦾 IT-Качалка Давида Шекунца 💪
2023-10-04 23:12
АХАХАХАХАХ да да да я именно эту серию и вспоминал в течении всего дня)))