Отказоустойчивое взаимодействие с медленным внешним сервисом?

Доброго времени суток.

Есть некий сервис, постоянно взаимодействующий с внешним сервисом (далее агрегатор).
Порядок взаимодействия примерно таков:
Сайт (laravel) -> api (laravel) (для общения с агрегатором) -> агрегатор* -> поставщик*
*приложения на работу которых нельзя влиять.

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

Проблема заключается в том, что время ответа агрегатора может доходить до 30-40 секунд и в пики посещаемости сайт падает по причине огромного кол-ва php-fpm процессов.

Вопрос заключается в том, как построить отказоустойчивое взаимодействие, при условии что:
1. Не имеет никакого смысла делать попытки кеширования/хранения Сущностей, так как:
1.1. Сущности могут быть изменены извне и нам необходимо это видеть.
1.2. Даже при кешировании Сущности А, останутся запросы к Сущностям XXX которые будут обращаться к медленному Сервису А.
2. Нельзя уменьшать время тайм-аута

Вертикальное/горизонтальное масштабирование результатов не приносит, увеличение кол-ва доступных php-fpm лишь немного отодвигает момент падения.

Единственный вариант приходящий на ум, вынести взаимодействие с агрегатором в очередь. Но, в таком случае возрастает сложность получения данных на фронте.

Было бы интересно выслушать похожий опыт решения проблем или ссылки на статьи.
  • Вопрос задан
  • 390 просмотров
Пригласить эксперта
Ответы на вопрос 4
Fragster
@Fragster
помогло? отметь решением!
Нужно класть задание в БД, получать в фоне, класть в БД ответ, затем на клиент прокидывать через пушер/аналог или если лень его настраивать - то с клиента раз в 5 секунд дергать "уже готово? а сейчас?"
Ответ написан
Griboks
@Griboks
Судя по всему, вы упёрлись в проблему ввода/вывода. И для её решения вы решили запустить побольше параллельных процессов. Однако, эти процессы ничего не делают кроме ожидания, поэтому тратят ресурсы впустую.

Обычно в таких случаях используют умную очередь сообщений. В большинстве языков это называется асинхронными потоками или просто async/await. Т.е. вы запрашиваете какие-то данные как await long_function(), и планировщик ресурсов просто прерывает выполнение процесса до получения результата.

С другой стороны, достаточно добавить в каждый процесс вызов системного ожидания вроде sleep(0.1), что позволит системному планировщику процессов также остановить текущий процесс на несколько тактов подряд.
Ответ написан
Комментировать
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
Урезоньте алгоритм, генерирующий безлимитно эти php-fpm процессы. Научите скрипт обработки прорабатывать несколько запросов, последовательно или параллельно (и да не забанит вас внешний сервис).
Ответ написан
Комментировать
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Тут только очереди, чтобы вся "тяжелая" работа делалалась в фоне.
А скрипты куда обращаются клиенты будут отрабатывать максимально быстро: данные есть - отдать, данных нету - создать задачу в очереди, данные подготавливаются - сообщить об этом.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы