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

silmarion

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

Как этого можно избежать?
 
Чтобы сайт не вешался, вызывай закрытие сессии перед курлом session_close()

А вообще, в таких случаях лучше использовать deffered queue
 
Ну он не совсем вешается, а ожидает завершения работы скрипта

Дело в том, что к одному и тому же скрипту (обычный curl Запрос) одновременно могут обращаться несколько пользователей, передавая свои параметры ему
На сайте висит форма, пользователь заполняет, нажимает отправить, данные передаются в скрипт аяксом, и получает ответ
 
И пока его не получил - сайт блокируется и пользователь не может открыть другие страницы. От этого спасет закрытие сессии, а вообще правильная реализация - deffered queue.
 
Спасибо, закрытие сессии вроде пока помогло, правда часть данных передавалась в сессии, но предварительно загнал их в переменные
А можно поподробнее про deffered queue, что это даст?
 
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 транзакции, у меня все записано, ищите!".
 
Использование CURL подробный режим , чтобы получить более подробную информацию , почему Curl скрипт висит . Это может быть, вы , отправив запрос HTTP от до HTTPS или какой-то другой причине .

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

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

Это то регистрирует в STDERR , или в файл, указанный с помощью CURLOPT_STDERR ( который принимает указатель на файл ) :
 
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 транзакции, у меня все записано, ищите!".

небольшое дополнение для увеличения стабильности/скорости:

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

- использовать curl_multi или его реализацию под названием "rolling curl".
 
У меня была похожая проблема! Версия Centos - 6.5!
Использование CURL подробный режим , чтобы получить более подробную информацию , почему Curl скрипт висит . Это может быть, вы , отправив запрос HTTP от до HTTPS или какой-то другой причине .

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

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

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