Ответ 1
У вас его нет точно. Когда причал использует разъем NIO (и только 9 поддерживает NIO), он работает следующим образом:
- Состояние ожидания как несколько потоков (1-4 в зависимости от # ядра), вызывающего селектор, ища активность IO. Это было увеличено до более чем 1 000 000 подключений на Jetty.
-
Когда селектор видит активность IO, он вызывает метод соединения в соединении, который:
- что-то еще зарегистрировалось, что он заблокирован, ожидая ввода-вывода для этого соединения, поэтому в этом случае селектор просто просыпается, кто бы ни был заблокирован.
- иначе поток отправляется для обработки соединения.
-
Если поток отправлен, он попытается прочитать соединение и проанализировать его. Теперь все зависит от того, является ли соединение http, spdy, http2 или websocket.
- для http, если заголовки запросов завершены, поток продолжает вызывать обработку запроса (в конечном итоге это попадает на сервлет), не дожидаясь содержимого.
- для http2/spdy требуется другая отправка, но см. обсуждение стратегии Eat-What-You-Kill в списке: http://dev.eclipse.org/mhonarc/lists/jetty-dev/msg02166.html
- для websocket вызывается обработка сообщений.
-
Как только поток отправляется сервлету, он выглядит так, как блокирует IO сервлета, но под уровнем HttpInputStream и HttpOutputStream все IO асинхронны с обратными вызовами. API блокировки использует специальный блокирующий обратный вызов для достижения блокировки. Это означает, что если сервлет выбирает использовать async IO, то он просто обходит блокирующий обратный вызов и использует асинхронный API более или менее напрямую.
- Сервлет может приостанавливаться с использованием request.startAsync, и в этом случае отправленный поток возвращается в пул потоков, но связанное соединение не помечено как заинтересованное в IO. Async IO может выполняться, но для события AsyncContext необходимо либо перераспределить поток, либо повторно зарегистрировать соединение для активности IO после завершения цикла асинхронизации.
Этот вид немного усложняется http2 и spdy, которые мультиплексированы, поэтому они могут включать дополнительную отправку.
Любая инфраструктура HTTP, которая не отправляет, может очень быстро работать в тестовом коде, но когда сталкивается с реальным приложением, которое может делать глупые вещи, такие как блок в базах данных, файловая система, службы REST и т.д.... тогда отсутствие отправки просто означает, что одно соединение может поддерживать все другие соединения в системе.
Для получения дополнительной информации о том, как причал обрабатывает асинхронную и диспетчерскую операции, см.: