За последние 24 часа нас посетили 17003 программиста и 1341 робот. Сейчас ищут 1566 программистов ...

GuzzleHttp и php-fpm

Тема в разделе "Настройка веб-сервера", создана пользователем alexpride1993, 30 дек 2017.

  1. alexpride1993

    alexpride1993 Новичок

    С нами с:
    28 мар 2016
    Сообщения:
    56
    Симпатии:
    20
    Всем доброго времени суток! Как говориться благими намерениями вымощена дорога в ад. Решили мы под новый год сделать нашим сотрудникам подарок и перевести нашу CRM на более мощный сервер, и из этого вышло ужасное. Помогите пожалуйста разобраться в причинах случившегося.

    Изначально система стояла (и стоит сейчас после отката) на машине под управлением Debian 8, версия nginx 1.10.3, php 7.1 (используется php-fpm).

    И вот, в три часа ночи мы взяли и перетащили все это дело на более мощную машину под управлением Debian 9, версия nginx такая-же как на старой. Конфиги скопипастили со старой машины, проверили, все работает, запустили народ, проверили что все работает и пошли спать.
    Система работала стабильно ровно 11 часов.
    В 3 часа дня наших девчонок, а потом и нас самих новый сервер "обрадовал" ошибкой 502 Bad gateway. Ну думаем, не беда, рестартнули php-fpm. Через несколько минут произошло тоже самое.
    Логи показали следующее:
    php-rpm:
    Код (Text):
    1. [pool www] server reached pm.max_children setting (5), consider raising it
    nginx:
    Код (Text):
    1.  
    2. 2017/12/29 15:26:36 [error] 29275#29275: *53168 upstream timed out (110: Connection timed out) while reading response header from upstream, client:
    3. адрес_клиента, server: наш_сервер, request: "POST адрес_апи HTTP/1.1", upstream:
    4. "fastcgi://unix:/run/php/php7.1-fpm.sock", host: "наш_сервер", referrer: "реферер"
    Ну ок, подняли до 20-ти, а потом и до 50-ти.
    php-fpm стал захлебываться значительно медленнее, но не перестал делать это впринципе. Диспетчер задач показывал что дочерние процессы плодятся как опухоль, медленно но верно приближаясь с текущему значению pm.max_children.
    Более того, у девочек отвалилась половина функций, общающихся по api с другими ресурсами. Копания в эту сторону показали что затык происходит при отправке запросов через клиент GuzzleHttp, скрипт просто зависает, что возможно и стало причиной, от которой произошло уже все остальное. Запросы, отправляемые напрямую через curl проходят исправно.
    Я сравнил версии библиотеки, обе они идентичные. Другие проекты тоже используют Guzzle, но таких проблем на них не наблюдается. На старом сервере, куда мы откатили систему все завелось сразу, никаких зависаний не было, следовательно я полагаю что что-то не так с настройками самой машины.
    В состояние когнитивного диссонанса вводит тот факт что ни рестарт служб, ни ребут всей машины никак не сказывается на ситуации, изначально система работала целых пол дня стабильно и исправно, код, отвечающий за работу с api после переноса не трогался вообще, и никакие настройки сервера на момент возникновения проблемы не менялись. Все просто возьми, да сломайся без видимых причин.

    Может кто сталкивался с подобным? Подскажите пожалуйста что могло сломаться, как это починить или в какую сторону копать дальше.

    UPD: сделал git reset --hard, и тем самым снес все изменения на новом сервере, которые были внесены в код после переноса. Проблема осталась, что еще больше заставляет меня склониться к тому что дело не в коде.
     
  2. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    http://docs.guzzlephp.org/en/stable/request-options.html#connect-timeout
    http://docs.guzzlephp.org/en/stable/request-options.html#timeout

    Попробуйте выставить таймауты. Судя по всему на каком-то этапе коннект виснет, а вместе с ними и процессы. Дальше уже разбирайтесь почему, к примеру может dns неправильно резолвятся, т.к. ip сменился, в кэше осталось другое значение и всё это дело зависает в бесконечном ожидании.
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.112
    Симпатии:
    1.243
    Адрес:
    там-сям
    @alexpride1993
    Если я правильно понимаю, веб срипт обращается к стороннему ресурсу и может зависнуть на этом. В итоге может накопиться много одновременно работающих потоков, каждый из них ждёт.

    1. Сделайте так чтобы не ждать: вынесите обработку исходящих запросов в очередь, а в веб скрипте только пополнйте эту очередь
    2. Guzzle это верхний уровень. На нижнем, насколько я понимаю, работает php_curl. Выставьте курлу таймаут поменьше, пусть возвращается с ошибкой не через 300 сек, а через 5. Итак понятно, что облом.
    3. Если причина в разрешении имён, посмотрите нельзя ли запрашивать по IP. А если нет, пропишите нужные имена в hosts чтобы резолвинг происходил мгновенно.