У нас есть API, реализованный в голой кости Scala Akka HTTP - пара маршрутов для тяжелых вычислений (интенсивность процессора и памяти). Нет кластеризации - все работает на одной мускулистой машине. Вычисление достаточно тяжелое - может потребоваться более 60 секунд для завершения одного изолированного запроса. И мы не очень-то заботимся о скорости. Там нет блокировки ввода-вывода, просто обработка процессора.Akka HTTP и длительные запросы
Когда я начал тестирование производительности, интересный образец показал: скажем, запросы A1, A2, ..., A10. Они довольно сильно используют ресурсы, и получается, что Akka вернет HTTP 503 для запросов A5-A10, которые перевернут. Проблема в том, что вычисление все еще работает, хотя никто не может найти результат.
И оттуда мы видим каскадное падение производительности: запросы A11-A20 поступают на сервер все еще работает над запросами A5-A10. Очевидно, что эти новые запросы также имеют шанс превышения - даже выше, если сервер более занят. Таким образом, некоторые из них будут работать к тому времени, когда Akka запускает тайм-аут, делая сервер еще более загруженным и медленным, а затем запускается новая партия запросов ... поэтому, немного запуская систему, вы видите, что почти все запросы после определенных точечный старт не работает с тайм-аутами. И после того, как вы остановите нагрузку, которую вы видите в журналах, некоторые запросы все еще обрабатываются.
Я попытался выполнить вычисление в отдельном ExecutionContext, а также диспетчер системы, пытаясь сделать его полностью асинхронным (через композицию Future), но результат все тот же. Затяжные задания делают сервер настолько занятым, что в итоге почти каждый запрос терпит неудачу.
Аналогичный случай описан в https://github.com/zcox/spray-blocking-test, но фокус смещен туда - /ping
не имеет для нас значения, так как более или менее стабильная ответственность за конечную точку, которая обрабатывает длительные запросы.
Вопрос: как мне разработать мое приложение, чтобы лучше прерывать вешающие запросы? Я могу терпеть некоторый небольшой процент неудачных запросов при большой нагрузке, но прерывание всей системы до остановки через несколько секунд является неприемлемым.
Довольно широкий вопрос. Короче говоря, вы должны немедленно отклонить некоторые запросы при большой нагрузке (просто скажите, извините или отследите пользователей, которые запускают слишком много вычислений или поддерживают очередь). Вы также должны использовать отдельные контексты для своих вычислений, базы данных, спрей ... поэтому ваш внешний интерфейс http всегда будет отвечать. – ipoteka