Пара слов обо мне. Начинал с эникейщика. Был DBA. Вырос до руководителя направления инфраструктуры в крупной энергокомпании. Очень ленив и все свои силы бросаю на то, что бы ничего не делать - делаю все чтобы все работало без сбоев и само.
Буков много, картинок нет.
История #1. Один админ против 50 тысяч человек с оружием.
Предыстория. В недавнее время в управлении моей команды находился региональный портал государственных услуг. Ранее, все охотники чтобы получить лицензию на отстрел просто подавали заявки на портале в удобное время и шли в поля, леса и на болота за добычей. В один момент чиновникам из ведомственного департамента стало скучно и принцип распределения поменялся на "кто первый подал заявку, того и тапки утки". Заодно ввел жесткий лимиты на добычу. Тем самым создав конкуренцию. Тем самым обеспечил единомоментный приток пользователей на портал который оказался к этому не готов.
Наступает час Х в первый рабочий день года. 50 тыс человек идут на портал и жмут кнопку "подать заявку" в надежде успеть быть одними из первых. Портал ложится. Админы перезапускают падающие сервисы и так по кругу. Далее сотни обращений в адрес регионального правительства, возмущения на форумах и тд и тп. Я пишу сотни заключений в извинительном тоне, нервничаю т.к. для меня это личное поражение и начинаю думать.
Естественно, были проведены предварительные работы по наращиванию ресурсов серверов, оптимизации настроек фронта, бэка и баз данных насколько это возможно. Нагрузочные тесты, эмулирующие поведение пользователей и т.д. Наступает следующий год - ситуация повторяется. Гипотезы повышения стабильности частично терпят крах. Я нервничаю вдвойне. Пролетаю с путевкой (сам охотился в то время).
Ситуация такова, что тестировать гипотезы в проде на живых пользователях можно 1 раз в год. Каждая ошибка - репутационный ущерб региональному правительству и мне лично.
Вспоминаю, что долгое время я был DBA и начинаю копать базу, а вернее лог медленных (более 3 сек) запросов, который скопился в пиковую нагрузку. Нахожу один запрос в сторону базы данных авторизации и хранения профилей пользователей. При обычной нагрузке он выполнялся за доли секунды. При нагрузке - 5. Вижу тяжелую для БД операцию сравнения с null. Беру лопату побольше и начинаю раскрывать бизнес логику которая его порождает.
Как оказалось, после авторизации пользователя в ЕСИА ответ от ЕСИА парсился приложением и данные в нашей БД обновлялись всегда. В момент заполнения формы эти же данные вытягивались из этой же БД для автозаполнения полей еще больше увеличивая нагрузку на нее.
В моей голове зажигается лампочка - а накой мы вообще принудительно обновляем данные в своей базе каждый раз если они меняются оооочень редко (адрес регистрации, ФИО и дата рождения по сути константы). И накой мы тянем из БД данные которые есть в кэше приложения когда мы получили их из ЕСИА.
Идея такая - не делать лишнюю тяжелую работу.
Реализация идеи - а давайте вычислим хэш-сумму по строкам в БД и будем его сравнивать с созданной тем же алгоритмом хэш-суммой данных из ЕСИА. И будем обновлять данные в БД только если это требуется. В итоге, вместо сравнения нескольких десятков полей из БД сравним одно, а обновим данные только если это нужно. Данные для формы тоже возьмем сразу от ЕСИА не дергая лишний раз БД.
Вроде все логично. Но приложение, по определенным причинам, может посчитать хэш-сумму только при реальной авторизации. Иными словами, нужно зайти каждому пользователю и только последующие авторизации отработают согласно идеи. Терпеть позор еще один год я был не готов.
Решение этой подзадачи - согласовываем информационное письмо, которые подтолкнет пользователей зайти на портал до часа Х. Суть письма такая - чтобы избежать отказа в услуге зайдите на портал и проверьте свои данные. Делаем рассылку. Пользователи распределено идут на портал и база наполняется хэш-суммами. Все хорошо, все по плану.
Наступает час Х - портал работает. Охотники счастливы, я счастлив в двойне. Проблема решена, я свечусь от счастья ярче сверхновой. Птичку жалко.
Вот так один запрос порождённый неисправимым ядром движка бэк-энда потребовал изменения тех процесса, привлечения ведомства и тысяч пользователей.
История #2. Порты тоже кончаются.
Есть сервис на 1с в которые летят тысячи оплат клиентов = деньги компании. К сервису подключены банки с жесткими требованиями на таймаут. При каждой ошибке при работе с нашим сервисом автоматом шлют письма какие мы плохие. Гендиректор пытается каждый неполученный рубль получить из моей премии. Ошибка возникает 1 - 2 раза в неделю на 2-5 секунд. За эти секунды компания недополучает несколько тысяч рублей. Процент ошибок составляет 0,0005% от общего количества запросов.
Естественно, админы говорят, что приложение не работает как надо, программисты говорят, что не работает сеть, схд тормозит и касперский все блокирует. Песенка стандартная и, думаю, всем известная.
Начинаем накручивать различные мониторинги производительности на проксях, бэк-энде, базе. Никакого криминала. Провести анализ за 5 секунд недоступности которая возникает в произвольный момент времени нет никакой возможности. Правило 3П (перезапусти - перезагрузи - переустанови) не дает результата.
Лампочка включилась. А что если бэк-энду не хватает портов сходить дальше и отработать как надо. Накручиваем заббикс на съем количества портов раз в 1 секунду (было несколько попыток интервалов) и видим. Да - в момент сбоя исходящие динамические порты кончаются. Вот это прикол, подумали мы. Накручиваем заббикс дальше чтобы понять кому они так понадобились в таком количестве. В итоге после нескольких манипуляция и аналитики видим. Агент системы СРК (Backup Exec) оставшийся там исторически в произвольный момент времени возбуждается, занимает все исходящие порты и успокаивается. Агент деинсталлирован. Сервис работает. Деньги текут рекой, жаль не ко мне.
История #3. Распутанная петля.
Кол-центр. Около 10 тысяч звонков в ��ень. 2 коммерческих колл-центра на подхвате чтобы переварить пиковую нагрузку. ВАТС на базе ПО Инфинити. В произвольный период времени ВАТС перестает принимать новые звонки, уже установленные вызовы работают без проблем.
Изначально пытались свалить проблему на нашего оператора номера 8800. Не вышло. Техподдержка Инфинити проблем тоже не нашла. Старый админ закатил скандал, попортил систему и уволился. Помимо остановки приема новых вызовов при пиковых нагрузках голос начинал квакать. Принято решение сократить время на обработку системой одного вызова для снижения общей нагрузки. Долгое время оптимизировали логику обработки звонков в IVR. Стало полегче. Но периодически новые вызовы переставали приниматься до рестарта сервиса.
Увидели закономерность, что за пару минут до проблемы начинается ассиметрия трафика в сторону оператора 8800. Входящий был, исходящий не был. Начали опять валить на него. Опять не вышло. Всеми правдами и неправдами выяснили, что наша версия ПО не способна переварить более 500 параллельных вызовов. Обновлённая версия стоит 10 млн + столько же на реализацию всех бизнес процессов. Дорого и не вкусно. Добавлю, что для ПО были задействованы 2 физические ноды по 2 ЦП. Но этого было мало.
Раз-два-три - лампочка гори. Изначальная схема движения вызова такая :
Пользователь - > 8 800 -> Инфинити (IVR) -> Коммерческий колл-центр - > Инфинити (наш оператор человек). Компетенции коммерческого колл-центра были ограничены и некоторые звонки возвращались к нам. Таким образом одна линия для Инфинити превращалась в 3 еще больше усугубляя проблему с нагрузкой. Петля на шее затягивалась.
Идея - развернуть виртуалку установив FreeSwitch и сначала направлять звонок в сторону коммерческого колл-цента как первую линию приема звонков. Так отсеялось 80% звонков, ушли все петли. Дышать стало легче и мне и серверам. В итоге и сам Инифинити виртуализировался высвободив физические хосты. Отказоустойчивость теперь на уровне виртуализации и никаких проблем с производительностью и резервированием. Бинго.
История #4. Черный понедельник. Как линукс убивал windows, а в итоге победил я.
Кластер Hyper-v. 10 хостов. 600 виртуалок. Которые пачками переезжают из старого кластера. С определенной даты каждый понедельник в районе 5 утра кластер вставал в позу. Часть ВМ переходили в read only режим взаимодействия с дисками и требовали ручного вмешательства админов. Единственная ошибка в логах хостов - таймаут при работе с СХД. В районе начала рабочего дня все само восстанавливалось. Почти все. Никаких пиковых нагрузок нигде не было. Хосты, СХД, Сети - всем хорошо. Кроме меня. Куча гипотез - все мимо. Но мой опытный взгляд зацепился за некоторую особенность поведения. Всегда плохело хосту на котором была роль мастер Hyper-v и таймаут был примерно на одних и тех же CSV. Долго пытались локализовать. В итоге выявили особенность, что согнав все ВМ на которых развернут кластер Minio S3 страдал именно этот хост, CSV где лежат диски этих ВМ и мастер нода Hyper. Как оказалось - в какой-то из версий ОС Ubuntu ребята разработчики сделали запуск процедуры fstrim в 00 00 + рандомное время в диапазоне 100 минут. Время на ВМ было по Гринвичу, что равно 5 00 утра в нашем часовом поясе. Как мы знаем, Windows не очень-то любит обработку множества маленьких файлов. В кластере s3 таких файлов у нас 96 000 000. И, когда fstrim начинал свои благие дела по очистке кластеров дисков в сторону службы хоста летел огромный поток команд типа unmap, которые потом транслировался в сторону CSV и СХД. Служба начинала тормозить и все погибало. Попробовали вызвать эту процедуру намеренно, увидели, что гипотеза верная и отключили ее совсем. Это была последняя пятница перед Новым годом. Все пошли наряжать елку со спокойной душой без необходимости поднимать системы в каникулы. Как то так.
