Является ли использование Servlet 3.0 асинхронным избыточным при развертывании на Tomcat с разъемом NIO? - PullRequest
0 голосов
/ 14 февраля 2019

Я видел эту ветку: Java - Async в Servlet 3.0 против NIO в Servlet 3.1 , но, похоже, это касается NI Servlet 3.1 (в отличие от коннектора Tomcat NIO HTTP).

Насколько я понимаю, настройка Tomcat с реализацией коннекторов HTTP NIO (по умолчанию в Tomcat 8 и более поздних версиях) фактическая работа по обработке запроса и созданию ответа выполняется в отдельном рабочем потоке, а также в потоках опрашивающего устройства, которые читают / пишутданные остаются разблокированными.

Похоже, это та же проблема, которую решает Async Servlet 3.0, в том, что работа над запросом / ответом выполняется в рабочем потоке, независимом от потоков http-соединения.

Так это два решения одной и той же проблемы?Другими словами, есть ли польза от написания моего кода асинхронно, если контейнер сервлета уже асинхронен?

1 Ответ

0 голосов
/ 17 февраля 2019

Это легче понять, если понять потенциальные места, где происходит IO в разных точках обработки запроса от контейнера до кода приложения.Задача коннектора контейнера (BIO / NIO) состоит в том, чтобы принять соединение сокета и передать его потоку, который в какой-то момент времени вызывает метод Servlet GET / POST.Теперь соединитель Tomcat NIO - это, по сути, решение контейнера использовать средство Java NIO ( Selector / Channel ) для обработки нескольких каналов ввода-вывода с меньшим количеством потоков.Selector предоставляет механизм для мониторинга одного или нескольких каналов NIO и распознавания, когда один или несколько становятся доступными для передачи данных, поэтому в контейнере селектора можно использовать один поток вместо нескольких для управления несколькими каналами.Эти готовые каналы затем обслуживаются потоками, число которых потенциально меньше, чем требуется в разъеме BIO.

В качестве отступления - на этом уровне проводится оптимизация уровня ОС для улучшения работы NIO.Например, Java поставляется с java.nio.channels.SelectorProvider реализацией, основанной на средствах уведомления о событиях epoll в Linux.Средство epoll доступно в ядрах Linux 2.6 и новее.Новая реализация SelectorProvider, основанная на epoll, является более масштабируемой, чем традиционная реализация SelectorProvider, основанная на опросе, когда в Selector зарегистрированы тысячи SelectableChannel.Новая реализация SelectorProvider будет использоваться по умолчанию при обнаружении ядра 2.6.Основанный на опросе SelectorProvider будет использоваться при обнаружении ядра до 2.6.

Теперь вернемся к рассматриваемой проблеме.До Servlet 3.0 вся обработка сервлета была синхронной, что было улучшено в Servet 3.0, так что метод GET / POST теперь возвращается немедленно, но без записи в ответ, если он не считается завершенным вызовом AsyncContext complete.Все идет нормально.Но была другая проблема.Обработка сервлета может потенциально включать чтение / запись во входной поток / выходной поток, доступный из запроса.Природа этого IO была все еще традиционной.Servlet 3.0 допускает асинхронную обработку запросов, но чтение / запись ввода-вывода по-прежнему было старым стилем, например, при чтении полезной нагрузки большого запроса от клиента с низкой скоростью поток блокировал бы ожидание данных - поэтому Servlet 3.1 неблокирует ввод-вывод для спасения, гдетеперь вы можете вызывать стиль обратного вызова вашей логики чтения / записи всякий раз, когда данные готовы, а не ожидающий их потокКак это работает в коде, можно увидеть здесь .

Мы все еще должны помнить, что IO базы данных (если таковой имеется) все еще остается традиционным IO ожидания.Эта область контролируется драйверами базы данных, которые придерживаются JDBC API и знают, что когда-нибудь они также предоставят API для неблокирующего ввода-вывода.Oracle уже ведет одну из таких инициатив Асинхронный доступ к базе данных , которая также похоже на использование Java NIO.Это проложит путь к тому, чтобы сделать обработку всех запросов неблокируемой.

...