Вы, похоже, действуете из-за неправильного понимания природы AsyncContext
и семантики ServletRequest::startAsync
. Этот метод (повторно) инициализирует AsyncContext
для запроса и связанного ответа, сначала создает его, если необходимо, и связывает его с парой запрос / ответ. Это переводит запрос в асинхронный режим , который по своей сути означает лишь то, что контейнер не будет считать обработку запроса завершенной, пока не будет вызван метод complete()
из предоставленного контекста .
В частности, создание асинхронного контекста не создает потоков и не назначает связанный запрос другому потоку, а методы AsyncContext
запускаются в вызывающем их потоке (хотя это и является технической особенностью для AsyncContext::start
). Контекст в первую очередь является объектом для любого асинхронного кода, который вы предоставляете для использования для взаимодействия с контейнером, что в противном случае он не смог бы сделать безопасно. Чтобы фактически выполнить обработку в каком-либо другом потоке, вам необходимо организовать существование этого потока и назначить ему работу. AsyncContext::start
- это удобный способ сделать это, но не единственный.
Относительно конкретно
как мне реализовать многошаговый ответ, в котором некоторые шаги блокируются с неблокирующими секциями между ними?
, основной ответ - "как хочешь". AsyncContext
не мешает и не помогает вам, потому что речь идет о связи с контейнером, а не о рабочем процессе. В частности, я не вижу необходимости или специального использования для вложенных AsyncContext
с.
Я думаю, вы описываете конвейер обработки с определенной ограниченной параллелизацией. Вы можете реализовать это, скажем, запустив весь рабочий процесс - я полагаю, все «блокирующие» шаги в потоке, запущенном через AsyncContext::start
, и перенесите другую работу в пул потоков, в каких бы единицах измерения ни было целесообразно. Имейте в виду, однако, что объекты запроса и ответа не являются потокобезопасными. В идеале основной поток извлекает все необходимые данные из запроса и выполняет все необходимые записи в ответ.
В качестве альтернативы, возможно, вы используете обычный поток обработки запросов для основного рабочего процесса, соответственно распределяете фрагменты работы в пул потоков и вообще пропускаете бит AsyncContext
. Нет необходимости в абсолютном смысле использовать AsyncContext
для выполнения асинхронных вычислений в веб-приложении - его назначение и модели обработки, для которых оно предназначено, являются гораздо более конкретными.