Почему выполнение cURL-запроса в PHP блокирует возможность отправки других cURL-запросов?

<b>Всем привет!</b> <br/> <b>Ситуация:</b> У нас есть страница на PHP с формой, где пользователи могут авторизоваться. Эта форма частично использует cURL для получения данных, доступных для выбора. При отправке формы происходит запрос к стороннему API (также через cURL), и на ответ API уходит около минуты ожидания. <br/> <br/> <b>Проблема:</b> Когда Пользователь #1 создаёт задачу, инициируется cURL-запрос к стороннему API, и пока не поступит ответ, задачи других пользователей остаются в ожидании. Дополнительно, поскольку форма, предназначенная для подгрузки значений, также использует cURL, активный запрос блокирует даже её формирование для других пользователей. <br/> <br/> <b>Вопрос:</b> Я пробовал использовать curl_multi_*, но не получил ожидаемого результата. Как решить данную проблему? Можно ли сделать так, чтобы cURL работал изолированно и не блокировал процесс для других пользователей сервиса?
  • 7 октября 2024 г. 19:15
Ответы на вопрос 2
Проблема, с которой вы столкнулись, связана с тем, что в PHP по умолчанию все запросы выполняются синхронно в одном процессе. Когда выполняется cURL-запрос, он блокирует выполнение других частей кода, пока не получит ответ, что и приводит к задержкам для других пользователей.

### Возможные решения:

1. **Использование `curl_multi_*`**:
   Если вы хотите выполнять несколько cURL-запросов одновременно, использование `curl_multi_*` является правильным подходом. Вы можете использовать `curl_multi_exec`, чтобы запускать несколько запросов одновременно. Убедитесь, что вы правильно настраиваете несколько дескрипторов cURL и обрабатываете их. Вот пример:

   ```php
   $mh = curl_multi_init();
   $handles = [];
   foreach ($urls as $url) {
       $ch = curl_init($url);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       curl_multi_add_handle($mh, $ch);
       $handles[] = $ch;
   }

   $running = null;
   do {
       curl_multi_exec($mh, $running);
       curl_multi_select($mh);
   } while ($running > 0);

   foreach ($handles as $ch) {
       $response = curl_multi_getcontent($ch);
       curl_multi_remove_handle($mh, $ch);
       curl_close($ch);
   }
   curl_multi_close($mh);
   ```

2. **Асинхронные запросы**:
   Рассмотрите возможность использования асинхронных запросов через AJAX на стороне клиента. Вместо ожидания ответа от сервера на сервере, вы можете отправить запрос и продолжить основную логику несмотря на ожидание ответа.

3. **Очереди задач**:
   Если ваш проект подразумевает длительные операции, такие как запросы к сторонним API, рассмотрите возможность использования системы очередей, например, RabbitMQ или Redis. Вы можете отправить задачу в очередь и обрабатывать её асинхронно, в то время как пользователь будет продолжать работать с приложением.

4. **Фоновые задачи**:
   Если доступность вашего API позволяет, рассмотрите возможность реализации фоновых задач (например, с помощью CRON или других систем), которые будут собирать данные периодически и хранить их в кэше или базе данных, чтобы уменьшить количество запросов к API.

5. **Параллельные процессы**:
   Если вы хотите, чтобы cURL-запросы действительно работали изолированно, вы можете запускать отдельные PHP-скрипты через команду `exec` или через `proc_open`, но это может потребовать больше настроек для управления процессами.

Выбор подхода зависит от архитектуры вашего приложения, загрузки и требований к производительности.
Где ты вы с асинхронностью проиграли) Скорее всего, вы выполняете запрос синхронно что приводит к блокировке основного потока выполнения программы
Похожие вопросы