Curl Скрипт вешает сервер

Тема в разделе "Как сделать...", создана пользователем silmarion, 22 июн 2015.

  1. silmarion

    silmarion

    Регистр.:
    21 июн 2012
    Сообщения:
    194
    Симпатии:
    19
    Приветствую
    На сервере висит curl скрипт, к которому обращаются пользователи сайта.
    Если скрипт запускает сразу несколько человек, сайт подвисает до окончания работы скрипта.

    Как этого можно избежать?
     
  2. BaBL

    BaBL Постоялец

    Регистр.:
    13 ноя 2012
    Сообщения:
    144
    Симпатии:
    87
    Чтобы сайт не вешался, вызывай закрытие сессии перед курлом session_close()

    А вообще, в таких случаях лучше использовать deffered queue
     
  3. silmarion

    silmarion

    Регистр.:
    21 июн 2012
    Сообщения:
    194
    Симпатии:
    19
    Ну он не совсем вешается, а ожидает завершения работы скрипта

    Дело в том, что к одному и тому же скрипту (обычный curl Запрос) одновременно могут обращаться несколько пользователей, передавая свои параметры ему
    На сайте висит форма, пользователь заполняет, нажимает отправить, данные передаются в скрипт аяксом, и получает ответ
     
  4. BaBL

    BaBL Постоялец

    Регистр.:
    13 ноя 2012
    Сообщения:
    144
    Симпатии:
    87
    И пока его не получил - сайт блокируется и пользователь не может открыть другие страницы. От этого спасет закрытие сессии, а вообще правильная реализация - deffered queue.
     
    silmarion нравится это.
  5. silmarion

    silmarion

    Регистр.:
    21 июн 2012
    Сообщения:
    194
    Симпатии:
    19
    Спасибо, закрытие сессии вроде пока помогло, правда часть данных передавалась в сессии, но предварительно загнал их в переменные
    А можно поподробнее про deffered queue, что это даст?
     
  6. 1n3gant

    1n3gant Создатель

    Регистр.:
    22 май 2015
    Сообщения:
    44
    Симпатии:
    4
  7. BaBL

    BaBL Постоялец

    Регистр.:
    13 ноя 2012
    Сообщения:
    144
    Симпатии:
    87
    Deffered Queue - это паттерн проектирования, не какая-то конкретная реализация, а принцип "как надо делать подобные вещи". В чем он заключается, давай на твоем примере предствим:

    1. куча клиентов посылают ajax на сервер
    2. сервер дергает курл, передает их данные на какой-то сервис
    3. клиент получает результат

    что плохо? Пока пункт 2 висит - клиент бездействует. Свяжь между сервером и сервисом оборвалась - клиент потерян (а представь что это у тебя заказы в CRM падают, ты потерял заказ, потерял клиента, потерял статистику продаж). А представь что речь идет об уведомлениях об оплате? Клиент оплатил - а ты не получил уведомления об этом, потому что сервер был недоступен. Сколько разбирательств и геммора?

    Как надо реализовать такие вещи:

    создаешь, к примеру, таблицу в БД (это и есть твоя queue:(
    Код:
    id, created_date, state, try, last_try_date, event_type, client_id, service_id, data_to_sent, data_received, success_callback
    на пункте 2, вместо того чтобы вызвать CURL, добавляешь строчку в таблицу и уведомляешь клиента что ваши данные получены, ждите ответа.

    Далее, независимо от клиента, cron скрипт вызывается 1 раз в минуту и проверяет, есть ли новые события (это state = 1, к примеру), забирает все новые события, пытается вызвать curl, если он прошел успешно - ставит data_received от сервиса, устанавливает state = 9 (исполнено) и дату. После этого вызывается success_callback (это имя функции для конкретного event_type, если у тебя их несколько) и отправляет письмо клиенту: "ваши данные отправлены на такой-то сервер, вы зарегистрированы". Ну или же при следующем посещении, или ajax'ом со страницы отправки, если юзер еще на ней - получаешь успешное событие и уведомляешь клиента.

    Если curl по каким-то причинам отвалился - добавляет try+1 (это чтобы ты при ревизии знал, сколько раз это событие пыталось уйти), не изменяет статус (через минуту снова событие попробует отправиться), можно записать информацию в data_received, тогда, если у тебя есть какая-то серьезная проблема, ты получишь какое-нибудь try=10000, state=1, data_received = fatal error, your server in FBI department. И сразу понятно, что клиент уведомление не получил, что в скрипте есть ошибка или сервер не доступен и прочее.

    В случае, если у тебя вопрос приема оплат идет - в data_received при успехе ты можешь хранить ID транзакции. Тогда, если платеж потеряется, сможешь предъявить яндексу: "Да как же так, вот же ваш ID транзакции, у меня все записано, ищите!".
     
    warg, redrik, rebux и 5 другим нравится это.
  8. nick dee

    nick dee Создатель

    Регистр.:
    15 дек 2015
    Сообщения:
    11
    Симпатии:
    18
    Использование CURL подробный режим , чтобы получить более подробную информацию , почему Curl скрипт висит . Это может быть, вы , отправив запрос HTTP от до HTTPS или какой-то другой причине .

    В вашем PHP , вы можете установить переменную CURLOPT_VERBOSE :

    curl_setopt ( $ локон, CURLOPT_VERBOSE , TRUE ) ;

    Это то регистрирует в STDERR , или в файл, указанный с помощью CURLOPT_STDERR ( который принимает указатель на файл ) :
     
  9. warg

    warg Постоялец

    Регистр.:
    26 июн 2007
    Сообщения:
    128
    Симпатии:
    131
    небольшое дополнение для увеличения стабильности/скорости:

    - добавить дополнительно например state = 2 а-ля "в процессе", который будет устанавливаться при вызове curl что-бы исключить дублирование запроса в ситуации когда запрос еще не успел
    до конца отработать и уже запустился следующий крон по графику.

    - использовать curl_multi или его реализацию под названием "rolling curl".
     
    nick dee нравится это.
  10. spas

    spas Писатель

    Регистр.:
    23 апр 2013
    Сообщения:
    9
    Симпатии:
    0
    У меня была похожая проблема! Версия Centos - 6.5!
    Использование CURL подробный режим , чтобы получить более подробную информацию , почему Curl скрипт висит . Это может быть, вы , отправив запрос HTTP от до HTTPS или какой-то другой причине .

    В вашем PHP , вы можете установить переменную CURLOPT_VERBOSE :

    curl_setopt ( $ локон, CURLOPT_VERBOSE , TRUE ) ;

    Это то регистрирует в STDERR , или в файл, указанный с помощью CURLOPT_STDERR ( который принимает указатель на файл ) :