Pull to refresh

С какой проблемой мы столкнулись на виртуальном хостинге

Hosting
Хочу поделиться опытом диагностирования и решения одной проблемы, которая появилась достаточно внезапно при использовании виртуального хостинга с PHP, и, в принципе, мало вероятна на хостингах другого типа.

Все началось, когда, в один прекрасный день, один сайт перестал открываться. Оказалось, что из-за загруженности сервера хостер решил перенести аккаунт на другой сервер. При этом не было уведомления ни до переноса, ни в то время, когда перенос начался. Это, конечно, было крайне некрасиво со стороны хостера, но не в этом суть. После переноса стали происходить странные вещи. Несколько дней стала наблюдаться следующая картина: при попытке отрыть любую страницу с сайта, она могла либо открыться моментально (как обычно), либо могла не открыться вовсе. Шанс на успех был примерно 50%. Я написал по этому поводу хостеру и посмотрел загрузку процессора, она оказалась феноменальной. В среднем за день выходило около 500% от отведенной мощности, а в некоторые часы загрузка была выше 1000%. До переноса среднесуточная нагрузка была в районе 50-60%.

Так как нагрузка изменилась от незапланированного переноса, я ожидал от хостера двух ответов: Либо что-то не так с конфигурацией на новом сервере (который, судя по нумерации, был действительно новый, и мог быть не корректно настроен), либо они перепутали тарифные планы, и за 100% бралась меньшая величина.

Но ответ был абсолютно другим: мы отключаем ваш аккаунт из-за его непомерной нагрузки на сервер и можем предложить перейти на выделенный сервер. Вот так, безапелляционно, без попыток проанализировать причину нагрузок и не обращая внимание на явную связь с переносом. Хорошо, что до этого был предоставлен скриншот, на котором хорошо было видно, что процессы именно нашего аккаунта висят в топе и, надо сказать, очень по долгу.

[тут была картинка]

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

Nex наспех написал регистратор всех запросов, пишущий в базу REQUEST_URI, точку входа, время старта, и если скрипт успешно выполнялся, время выполнения. После анализа логов было окончательно выяснено, что время выполнения не зависит ни от чего и является случайной величиной, и лежит в пределах положенных 0,1—1,0 с, либо 40—120 с, и редко когда в пределах 1,0—40 с.

В конечном итоге, разбирательство дошло до одной строчки с функцией session_start(), комментирование которой полностью избавляло от проблемы. Осталось только разобраться, почему. Первым делом, было подозрение, что CMS использует session_set_save_handler, и криво переназначает функции. Но следов этой функции найдено не было. Потом мы стали анализировать установленные переменные окружения для сессий. Папка для хранения сессий (session.save_path) была /tmp. В принципе, уже на этом этапе было ясно, что дело, скорее всего, в этом, и скрипты тупят, когда PHP пытается почистить папку от истекших сессий. Но почему чистка запускалась так часто при gc_divisor равном 100, было не ясно. Впрочем, ответ нашелся очень быстро. Оказалось, что gc_divisor работает в паре с gc_probability, который по умолчанию равен 1, но в конфигах CMS был задан равным 40, что означало, что каждые 4 запуска из 10 производилась чистка. Это как раз и объясняло ~50% шанс на нормальное выполнение скрипта. Ну а связать это все с переездом на другой сервер было уж совсем просто: на новом сервере была изрядно захламленная папочка /tmp с намного большим количеством файлов.

Все проблемы были решены переназначением save_path в собственную временную папку и установкой gc_divisor в дефолтовую единичку. Разработчики, старайтесь всегда проверять эти значения на своих проектах.

Но, на самом деле, интересна еще одна вещь. Допустим, количество скриптов, которые используют сессии — 50%. Допустим также, что 50% из них используют дефолтовые настройки. Получается, что 400 запросов скриптов будут выполнены за 0,5*400 = 200 секунд, и потом запустится один скрипт, который вызовет дефолтовый чистильщик старых сессий, который, при достаточной захламленности папки, будет выполняться 120 с. Получается, что солидную часть времени сервер занят бесполезной работой. Так что, админы, будьте так же внимательны.

Ps. Об устранении проблем было сообщено хостеру немедленно, а через день, когда нагрузка уже выровнялась, нам пришло чудесное письмо, в котором хостер просил разобраться с непомерной нагрузкой, и грозился отключить аккаунт. Хорошо, когда в конторе несколько менеджеров и администраторов. Но когда каждый не знает, чем занят другой, конечно, плохо.

PPs. Хостера не упомянаю сознательно.
Tags:
Hubs:
Total votes 58: ↑53 and ↓5 +48
Views 2.4K
Comments Comments 115