Итак, исходные данные следующие:
- ваша программа выдает тысячи запросов в секунду к службе REST,
- POST-запрос занимает больше 1 секунды,
- заканчивается поток из пула потоков.
Первое, что вы должны проверить: сколько одновременных запросов может выполнить служба REST? Может ли быть так, что он не может обрабатывать тысячи запросов в секунду, а большая синхронизация одного запроса является результатом перегрузки службы? Затем вы должны установить механизм ограничения скорости ваших запросов. На самом деле, устанавливать такой предел - хорошая идея при любых обстоятельствах.
Во-вторых, вы должны решить, может ли такая скорость доступа быть достигнута с помощью синхронного или асинхронного ввода-вывода. Синхронный ввод-вывод проще и быстрее, но требует большего расхода памяти для потоков. Грубая оценка выглядит следующим образом:
- менее 100 одновременных запросов: используйте синхронизацию
- более 10000 одновременных запросов: используйте async
- между: в любом случае
Если вы решили использовать синхронный ввод-вывод, то самый простой и естественный способ установить ограничение частоты запросов - это использование семафора: поток, желающий выполнить следующие запросы, получает объект семафора, а после получения ответа освобождает его , Оставьте количество потоков в пуле потоков равным пределу запроса.
Если вы решили использовать синхронный ввод-вывод, то универсального механизма для установки такого ограничения не существует, поскольку асинхронные семафоры обычно недоступны для разработчика. Если ваша асинхронная библиотека ввода / вывода имеет реактивный интерфейс, используйте ее (асинхронные семафоры являются частью механизма противодавления). Если нет, вы можете создать такой механизм из следующих компонентов:
- очередь блокировки для асинхронных запросов
- ограничивающий семафор
- поток, который в цикле делает следующее: получает семафор, получает следующий запрос из очереди и выдает его. Когда запрос завершен (независимо от того, успешно он или нет), семафор освобождается обратным вызовом запроса.
Этот механизм использует один поток для всех асинхронных запросов, поэтому он занимает не так много памяти и работает достаточно быстро. Однако, если вам нужно, чтобы он работал быстрее, просто увеличьте количество потоков.