Некоторое время назад от заказчика поступила заявка с формулировкой "зависание базы во время массовой активности пользователей". Также заказчиком было упомянуто, что у них используется MS SQL, запущенный на серверной операционной системе семейства Windows.
Казалось бы, что можго пойти не так? Но ход и результаты диагностики, на мой взгляд, достойны отдельной статьи.
Итак. Какая следует реакция со стороны поддержки? Заявка назначается на инженеров, специализирующихся на стеке решений Microsfot.
Эти инженеры оперативно выясняют, что на сервере на самом деле используется СУБД не MS SQL, а вовсе даже MySQL. Какой-то опыт работы с ним они тоже имеют, и начинают инженеры изучать состояние СУБД, проверять метрики узла, следить за нагруженностью ввода-вывода, процессора и памяти, пытаясь найти узкие места в производительности. Заказчику отправляют отчёты, в трекинг пишутся протраченные часы, время идёт, даются рекомендации по увеличению размера буфера InnoDB, но "зависания базы" сохраняются.
В какой-то момент заявка переходит к инженерам, специализирующимся на *nix, в том числе, потому что:
- на сервере кроме MySQL, работает еще и Apache Web Server и PHP, т.е. это классический WAMP;
- сервер работает в среде виртуализации Proxmox;
- в планах заказчика появилась мысль вернуть сервер на linux based операционную систему.
При дальнейшем погружении в задачу было установлено, что проблем с зависанием СУБД нет, а то, что называлось "зависанием базы", было зависанием обращений пользователей из браузера к порталу. Также выяснилась интересная особенность - в момент "зависания", как оказалось, у некоторых пользователей сохранял свою работу.
В этот момент возникло подозрение, что проблема на самом деле проще. И "поймав" момент с зависанием портала было проверено количество установленных соединений к вебсерверу с помощью "банальной" команды:
netstat -an | findstr 8080 | findstr ESTA | Measure-Object -Line
Которая показала, что соединений ровно 150.
В чём же проблема? А проблема банальна. С момента принятия в далёком 1999 версии 1.1 протокола HTTP браузер, после успешного получения ответа от вебсервера, не разрывает соединение, а оставляет его "на всякий случай" для возможных следующих вопросов. Так как пользователей у портала было действительно много, а браузеры открывали по несколько подключений к вебсерверу, то в часы пиковой нагрузки количество установленных соединений достигает значения переменной ThreadsPerChild, которое в используемой версии apache web server установлено в 150. А новые подключения от пользователей не принимаются и ожидают завершения открытых ранее соединений. Отдельно стоит отметить, что с точки зрения классических метрик производтельности по занятости CPU, памяти, ввода-вывода и сети всё выглядит идеально - нагрузки нет. Увеличение значения ThreadsPerChild в два раза решило проблему с периодической недоступностью портала.
Что хотелось бы сказать по итогам этой заявки?
Пользователям:
- при обращении в техническую проблему старайтесь по возможности технически правильно формулировать проблему и использовать правильные термины, чтобы не возникало ситуации, когда поддержка пытается искать проблему в MS SQL, когда нет ни только проблем с MS SQL, но и самого MS SQL;
- адекватно реагировать на уточняющие вопросы технической поддержки, даже если некоторые из них Вам кажутся странными. "когда проблема появилась первый раз", "какие были сделаны изменения", "как часто проявляется проблема", "проблема затрагивает всех пользователей или только их часть" - это всё вопросы, которые могут помочь найти проблему методическим путём, а не "перебором".
Поддержке: проблема может быть банальная и лежать на поверхности, но для того, чтобы понять причину её возникновения всё таки надо понимать "как это работает". Например, в данном случае, знать про существование Keep-Alive в HTTP начиная с версии 1.1.