notes_devops_engineer
125 subscribers
8 photos
1 file
43 links
Записки DevOps инженера
Download Telegram
Forwarded from The Last of 9s
ConnectionProblems.png
72 KB
#кулстори #connectionpool

вводные:
представим, что есть у нас классный бэкенд, он готов обрабатывать много запросов, он стейтлесс, поэтому мы с вами ожидаем, что мы его легко можем замасштабировать горизонтально. для верности мы даже проведем нагрузочные тесты и по-прежнему все отлично, при пиковой нагрузке добавляем +1 инстанс и выдерживаем её.

проблема:
запускаем нашего красавчика в проде и дальше видим, что происходит ужасное, у нас в 100% cpu утилизирован 1 под. изучив логи, трейсы и другую телеметрию становится ясно - только этот под обрабатывает запросы, а остальные из ReplicaSet стоят, курят. скажите "виноват балансировщик"? смотрим дальше и выясняем, что запросы летят от соседнего сервиса (сервиса А) и ходит он по svc name, запросов довольно мало, то есть между вами никакого балансировщика нет.

что же происходит?
чтобы не тратить драгоценные миллисекунды и ресурсы на tcp-хендшейки, клиенты используют пулы соединений (connection pools). благодаря http keep-alive, однажды открытое соединение не закрывается, а кладётся в пул, чтобы его можно было быстро переиспользовать.
и вот что получается на практике:
1. наш сервис А (клиент) хочет сделать первый запрос. он обращается к dns: "дай айпишник для svc name".
2. dns честно отдаёт ему ip одного из подов сервиса Б.
3. клиент устанавливает с этим конкретным подом соединение (открывает сокет) и отправляет запрос.
4. получив ответ, он не рвёт коннект, а аккуратно возвращает его в свой пул.
когда прилетает второй, третий, сотый запрос. зачем клиенту снова идти в dns и создавать новый коннект, если есть готовенький коннек? он просто берёт его из пула. в итоге все запросы летят в один и тот же под сервиса Б, и вся наша красивая схема с горизонтальным масштабированием не работает.

как решить проблему?
например, можно пустить трафик через ингресс - через него идет, скорее всего, много трафика и поэтому пулы коннектов будут шире. в таком случае нжинкс или любой другой балансировщик будет держать свой набор сокетов и коннектов к сервису Б, за счёт чего размажется трафик. это добавляет латенси, но вот прям элегантные решения пока не нашел :)

знайте! ваши запросы не балансируются через service ip сущность кубрнетеса, через нее происходит только резолвинг, а сами коннекты в итоге устанавливаются pod2pod, и запросы летят тоже pod2pod