32

Вопрос по ajax – Я не понимаю поддержку Async в сервлетах 3.0 API

Я пришел из Java SE, и я сделал несколько руководств по сервлетам и прочитал Head First JSP & amp; сервлет. Я читаюJavaWorld.com статья о поддержке Async сейчас, но я не совсем понимаю.

Что такое Async просто? В чем разница между Ajax и Servlet Async?

P.S. У меня есть фон PHP с ajax, и я знаю концепцию, но я не пробовал его с java.

  • В вашем примере вы должны завершить процесс, вызвав complete (), как вasyncContext.complete() в противном случае вызов клиента jQuery, ajax приводит к ошибке:

    от
  • Я не совсем понимаю, как перемещение одного потока из одного пула в другой может иметь значение с точки зрения масштабируемости. Я вижу смысл возвращать поток прослушивателя сервера в пул, но я не знаю, может ли это значительно улучшить масштабируемость вашего приложения.

    от
  • Спасибо! Я искал в Интернете эту тему, но почти все найденные мной примеры обмениваются только одной веткой с другой и НЕ обсуждают эту проблему! Я думаю, что большинство людей просто используют асинхронную обработку (тупо), не зная, что они делают / почему они это делают.

    от
  • Большое спасибо Арджану, первый абзац действительно ясен и понятен.

    от Ismail Marmoush
  • Обмен потоками не поможет с масштабируемостью, но посмотрите пример загрузки. Некоторые потоки могут поддерживать несколько асинхронных соединений. Если запрос может быть разбит на несколько задач, которые могут быть поставлены в очередь и тому подобное, возможно, стоит рассмотреть этот режим. В противном случае, действительно, не так много ожидаемых выгод.

    от
  • 82

    В традиционной модели сервлета обычно бывает так

    что 1 запрос соответствует 1 потоку.

    Эти потоки обычно приходят из пула, который управляется контейнером сервлетов. Контейнер сервлетов может обрабатывать только новые запросы, если в этом пуле есть свободные потоки. Пока ваш собственный код занят обработкой запроса, поток не свободен.

    В некоторых ситуациях может стоить сломать эту модель. Что происходит, так это то, что запрос поступает в сервлет через такой поток, управляемый контейнером сервлета, и ваш код запрашивает асинхронное выполнение. Затем вы можете вернуться из запроса сервлета, и поток контейнера будет освобожден.

    В отличие от синхронной обработки запросов, это не будет подтверждать какой-либо ответ и не будет закрывать соединение. Вместо этого вы можете передать асинхронный контекст другому пулу потоков, который может его забрать, и, когда какой-то поток сможет его обработать, обслужит его и сможет писать в ответ.

    Пример:

    @WebServlet(urlPatterns = "/somepath", asyncSupported = true)
    public class AsyncServlet extends HttpServlet {
    
        @EJB
        private AsyncBean asyncBean;
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            AsyncContext asyncContext = request.startAsync();
    
            // The following line will not block and return immediately
            asyncBean.doAsyncStuff(asyncContext);
    
        } // Shortly after this method has ended, thread will be returned to pool
    }
    

    СAsyncBean реализуется как:

    @Stateless
    public class AsyncBean {
    
        @Asynchronous
        public void doAsyncStuff(AsyncContext asyncContext) throws IOException {
            asyncContext.getResponse().getWriter().write("test");
        }
    }
    

    В приведенном выше коде, где-то вскоре после возвращения изAsyncServlet#doGet() метод, поток сервлета будет возвращен в пул. «Запрос»; (задание) для выполненияAsyncBean#doAsyncStuff() будет помещен в очередь для сбора пула потоков EJB.

    Ответ на вопрос «ПОЧЕМУ и КОГДА вы будете использовать это» не так прост. Если вы просто хотите сохранить потоки, то в приведенном выше случае вы должны были бы заменить один поток из одного пула потоков на другой (в этом случае пул сервлетов против асинхронного пула EJB), и чистая выгода не будет такой большой. Вы могли бы также дать вашему пулу потоков сервлетов дополнительный поток.

    Однако в более сложных сценариях вы можете выполнять более детальное управление запросами; разделите их на несколько задач и создайте пул потоков для обслуживания этих задач. Например. Представьте, что 100 запросов на загрузку файла размером 10 МБ, обработанного 10 потоками, которые дает циклический перебор, отправляют 100 КБ времени на каждый запрос.

    Еще одно приложение - это запрос, который должен ожидать данные от внешней системы, и где эта внешняя система способна отправить сообщение, которое может быть передано обратно запрашивающей стороне. То есть вызов базы данных здесь не имеет смысла, поскольку в любом случае вам понадобится другой поток, ожидающий ответа. Тогда вы бы снова сменили один поток на другой. Но если вам нужно дождаться, например, входящего письма, одна ветка может дождаться любого письма и передать его на любой приостановленный запрос.