在处理请求时使用异步Servlet以及dispatch()和complete()方法的行为

Cha*_*har 10 java concurrency asynchronous servlets guava

我正在使用异步Servlet来处理请求,

根据Docs :( complete(),dispatch())

????????????????????????????????????????????????????????????????????????????????
? void complete()  ? Completes the asynchronous operation and closes the       ?
?                  ? response associated with this asynchronous context.       ?
?                  ? You call this method after writing to the response object ?
?                  ? inside the asynchronous context.                          ? 
????????????????????????????????????????????????????????????????????????????????
? void dispatch()  ? Dispatches the request and response objects               ?
?                  ? of this AsyncContext to the servlet container.            ?
????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

我无法理解async.dispatch(),async.complete()及其工作原理.
我对此几乎没有疑问:

  1. 究竟有什么区别async.dispatch()async.complete()
  2. 当我调用dispatch()(在run(()内部时,响应到达客户端,这意味着我们可以异步推送响应?
  3. 如果我asyncContext.dispatch()先调用asyncContext.complete(),那么线程的行为是什么?
  4. 如果我之后调用任何方法asyncContext.complete(),该方法调用会发生什么,如下所示代码(在同一个中run())?
    [当我测试它时它工作正常并显示相同的线程ID]
  5. 如果我在内部调用异步方法,run()我是否需要完成asyncContext.complete()内部回调()?(onSuccess()或onFailure())
  6. 是否有任何关于此的帮助(示例来源/书籍/在线帮助)?(异步Servlet和期货组合)

    final FutureCallback<Void> calculateTime= new CustomFuture<>(calculate);
     // start Async context.
     final AsyncContext asyncContext = request.startAsync();
    
      asyncContext.start(new Runnable() {
            @Override
            public void run() {
    
                MyObject object= null;
                try {   
                    object= myFactory.create();
                    //dispatch async context
                    asyncContext.dispatch("Object Successfully Created"); 
                } catch (final IOException e1) {
                    logger.error("logging error");      
                }
                asyncContext.complete(); //complete async context
    
                // call asynchronous method
                final ListenableFuture<Void> future = myService.doSomething();
    
                Futures.addCallback(future, calculateTime);
                // calling asyncContext.complete() here will work?
            }
        });
    
    Run Code Online (Sandbox Code Playgroud)

    提前致谢.

ant*_*tix 16

从马的嘴里(Oracle Javadoc)

完成()

完成在用于初始化此AsyncContext的请求上启动的异步操作,关闭用于初始化此AsyncContext的响应.

任何类型为AsyncListener的侦听器都将在其onComplete方法中调用,这些侦听器是为创建此AsyncContext的ServletRequest注册的.

dispatch(字符串路径)

将此AsyncContext的请求和响应对象调度到给定路径.

...

对请求和响应的控制被委托给调度目标,并且在调度目标完成执行时将关闭响应,除非调用ServletRequest#startAsync()或ServletRequest #startAsync(ServletRequest,ServletResponse).

Q/A

  1. dispatch和之间有什么区别complete

    调用complete告诉容器触发onComplete侦听器并停止异步模式,dispatch基本上告诉容器调用complete然后将请求(内部)转发到指定路径.该路径可以是JSP,同步servlet,甚至是另一个将触发新一轮异步处理的异步servlet.

  2. 当我dispatch在内部调用run响应到达客户端时,这是否意味着我们可以像这样异步推送响应?

    相反,dispatch关闭异步模式并将请求转发给另一个servlet或JSP.要将数据推送到客户端,您必须写入Response与之关联的对象AsyncContext.

  3. 如果我dispatch先调用complete,那么线程的行为是什么?

    未定义,这是一种很好的说法,取决于容器的实现方式.也许它会抛出一个错误,也许onComplete处理程序会被触发两次,也许会调用complete什么也不做,也许你的线程和容器之间会有一个竞争条件,在调用处理程序和操作内部结构的AsyncContext实现等.

  4. 如果我调用任何方法后,complete会发生什么是方法调用

    取决于你打电话的方法.规范声明如果调用后将dispatch抛出,其他任何未定义的特定实现.IllegalStateExceptioncomplete

  5. 如果我在内部调用异步方法run应该complete在callback()内调用?

    是的,complete一旦完成,你必须调用完成异步处理.该run方法用于调度由容器管理的线程池执行的任务,并且可以在异步请求的生存期内多次调用它.

  6. 有没有使用Async Servlets和期货组合的例子?

    我不知道,但在"另请参阅"部分中有一些使用异步servlet链接的好例子.原则上我认为使用期货没什么价值.请参阅:"async servlet是否适合我正在做的事情?"

异步servlet是否适合我正在做的事情?

异步servlet的目标是减少为某些类型的"推送客户端"提供服务所需的线程数:HTTP请求保持打开状态,直到发生(通常是外部)事件,然后服务器将数据推送到通道.在标准的servlet环境中,每个客户端将分配一个专用线程并等待,从而消耗宝贵的系统资源.在异步模式下,客户端连接可以"保持"并从执行线程中分离,直到事件发生,从而可以对其执行某些操作.以在线聊天应用程序为例.所有连接的客户端将处于空闲状态,直到有人向房间发送消息.为每个连接的用户保留专用线程是浪费的.

如果您的应用程序需要同时调用多个服务,并且您希望使用期货和执行程序来并行化该操作,那么异步servlet可能不太合适:您将无法获得任何东西,并且标准servlet将更容易实现.另一方面,如果服务调用可以以异步(非阻塞)方式进行,而不依赖于线程执行程序,那么这是另一个故事.

要问的"正确"问题是:我是否希望拥有比活动连接更少的线程?


也可以看看: