异步Servlet的理解与实践

AsyncContext理解

Servlet 3.0(JSR315)定义了Servlet/Filter的异步特性规范.
怎么理解"异步Servlet/Filter"及其使用情景?api

Servlet3.0之前

流程:

  1. 容器初始化ServletRequest与ServletResponse对象.
  2. 容器调用Servlet实例的service(ServletRequest, ServletResponse)执行业务逻辑.
  3. 容器Commit ServletResponse, 将响应结果写回客户端并关闭链接.异步

    • Servlet接口定义
    public interface Servlet {
        public void init(ServletConfig config) throws ServletException;
        public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException;
        public void destroy();
    
        public ServletConfig getServletConfig();
        public String getServletInfo();
    }
    • Filter接口定义
    public interface Filter{
        public void init(FilterConfig filterConfig) throws ServletException;
    
    }

局限

  1. 执行完流程(2)后当即Commit ServletResponse, 将响应结果回写给客户端.
  2. 局限(1)致使请求的全部业务逻辑都必须在service()方法内同步执行.
  3. 局限(2)致使容器的控制线程耗用严重, 特别是长链接或者阻塞等待(DB,IO,Net)的情景.

看到这里, 是否是有点明白了!async

Servlet 3.0前, Service容器调用Servlet.service()方法后就会Commit与销毁ServletResponse, 这致使全部业务逻辑都必须在service()内处理, 无论理是耗时仍是不耗时的, 控制线程必须等待处理完成才能"抽身"服务新的请求.spa

Servlet 3.0 规范提供AsyncContext设施实现ServletResponse的delay commit.线程

AsyncContext原理

经过ServletRequest.startAsync()通知Servlet容器delay ServletResponse的committal, 并返回AsyncContext对象供其余线程在service()方法结束后使用.code

AsyncContext套路

  1. 设置asyncSupported=true.
    • 在<servlet>或<filter>内使用<async-supported>标签
    • 在@WebServlet或@WebFilter内使用asyncSupported属性
  2. 调用ServletRequest.startAsyc()通知容器delay ServletResponse的committal, 并返回AsyncContext对象.
  3. 调用AsycContext.setTimeout()设置超时; 调用AsyncContext.addListener()添加监听器,设置start/timeout/error/complete的回调方法.
  4. 将AsyncContext对象交给工做线程处理.
    • 自定义线程池: ThreadPoolExecutor
    • 容器线程池: AsyncContext.start()
  5. 控制线程继续服务其余请求.
  6. 工做线程完成处理, 响应结果回写客户端.
    • 正常完成: 手工调用AsyncContext.complete()
    • 处理超时或发生错误, 自动调用AsyncContext.complete().
      只有AsyncContext.complete(), ServletResponse才会提交, 响应结果才会回写客户端.
    • 分发其余: 调用dispatch分发其余Servlet处理.

最佳实践: 慎重AsyncContext.setTimeout(0)对象

AsyncContext相关的API:

ServletRequest:

  • ServletRequest.isAsyncSupported()
  • ServletRequest.isAsyncStarted()
  • ServletRequest.startAsync(...) #多个
  • ServletRequest.getAsyncContext()

AsyncContext:

可分红下述几类接口

  • AsyncContext.getRequest()/getResponse()/hasOriginalRequestAndResponse()
  • AsyncContext.setTimeout()/getTimeout()
  • AsyncContext.addListener(...)/createListener()
  • AsyncContext.complete()/dispatch(...)
  • AsyncContext.start()
相关文章
相关标签/搜索