资讯专栏INFORMATION COLUMN

17.12 异步处理

atinosun / 211人阅读

摘要:异步处理是指给这些阻塞操作分配一个新线程,并把关联请求处理的线程返回给容器。异步处理支持和的异步处理。在一个上启用异步处理,设置注解的参数为,如下类提供在方法中执行异步处理所需的功能。

应用服务器的web容器通常会为每个请求分配一个服务线程。在重负载的场景下,容器需要大量的线程去服务所有客户端请求。服务可扩展性的限制包括内存不足或者耗尽容器线程。创建可扩展web程序,你必须确保没有关联请求的线程是空闲的,所以容器可以使用他们处理新请求。
这里有两个关联请求的线程空闲的两个场景:

线程需要在构建响应之前等待一个资源可用或者处理数据。例如,一个应用程序需要在构建响应前查询数据库或者通过远程web服务访问数据。

线程需要在构建响应之前等待一个事件。例如,线程在构建响应之前需要等待一个JMS消息,另一个客户端的新信息,或者队列里面的新数据可用。

这些场景代表限制web程序可扩展性的阻塞操作。异步处理是指给这些阻塞操作分配一个新线程,并把关联请求处理的线程返回给web容器。

servlet 异步处理

java ee支持servlet和filter的异步处理。如果一个servlet或一个filter处理请求时可能到达一个阻塞操作,它可以把操作分配给一个异步处理上下文并且在不生成响应的情况下将关联请求处理的线程回送给web容器。阻塞操作在不同线程的异步上下文中执行完成,它可以生成响应或者转发请求到另一个servlet。
在一个servlet上启用异步处理,设置@WebServlet注解的asyncSupported参数为true,如下:

@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet { ... }

javax.servlet.AsyncContext类提供在Service方法中执行异步处理所需的功能。获得一个AsyncContext实例,在service方法中调用request对象的startAsync()方法;例如:

public void doGet(HttpServletRequest req, HttpServletResponse resp) {
   ...
   AsyncContext acontext = req.startAsync();
   ...
}

这个调用将请求进入异步模式并且确保响应在退出service方法时每月被提交。你必须在异步上下文完成阻塞操作时生成响应或者转发到其他servlet中。
AsyncContext类提供的基础功能描述:
方法签名:void start(Runnable run)
描述:容器提供的能提供阻塞操作处理的不同线程
方法签名:ServletRequest getRequest()
描述:返回用来初始化异步上下文的请求。在上面的例子中,request与service方法中的相同。你可以通过这个方法在异步上下文中从请求中获取参数。
方法签名:ServletResponse getResponse()
描述:返回初始化异步上下文的响应。在上面的例子中,response与service方法中的相同。你可以在异步上下文中,使用这个方法写入阻塞操作的结果到响应中。
方法签名:void complete()
描述:完成异步操作,并关闭与此异步上下文关联的响应。你可以在异步上下文完成写入响应后调用这个操作。
方法签名:void dispatch(String path)
描述:转发请求和响应到给定的路径。在阻塞操作完成后,使用这个方法调用另一个servlet写出响应。

等待一个资源

这个章节示范了怎么使用AsyncContext上下文提供的功能,有如下用例:

servlet从一个GET请求中获取参数

servlet使用一个资源,比如一个数据库或者一个web service,基于这个参数获取信息。这个资源可能比较缓慢,所以这可能是一个阻塞操作。

servlet使用资源的结果生成响应。

下面的例子是一个不使用异步处理的常见servlet:

@WebServlet(urlPatterns={"/syncservlet"})
public class SyncServlet extends HttpServlet {
   private MyRemoteResource resource;
   @Override
   public void init(ServletConfig config) {
      resource = MyRemoteResource.create("config1=x,config2=y");
   }

   @Override
   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) {
      response.setContentType("text/html;charset=UTF-8");
      String param = request.getParameter("param");
      String result = resource.process(param);
      /* ... print to the response ... */
   }
}

下面的示例是同一个servlet,但使用了异步处理:

@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {
   /* ... Same variables and init method as in SyncServlet ... */

   @Override
   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) {
      response.setContentType("text/html;charset=UTF-8");
      final AsyncContext acontext = request.startAsync();
      acontext.start(new Runnable() {
         public void run() {
            String param = acontext.getRequest().getParameter("param");
            String result = resource.process(param);
            HttpServletResponse response = acontext.getResponse();
            /* ... print to the response ... */
            acontext.complete();
   }
}

AsyncServlet在@WebServlet注解属性中添加asyncSupported=true。其余的差异在service方法中:

request.startAsync() 引发request被异步执行;response不会在service方法结束时发送到客户端;

acontext.start(new Runnable() {...})从容器中得到一个新的线程。

内部类中的run() 中的代码在一个新线程中执行。内部类需要从异步上下文中读取请求参数和写入响应。调用异步上下文的complete()方法来提交并发送响应到客户端。

AsyncServlet的service方法立即返回,同时请求在异步上下文中处理。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74257.html

相关文章

  • 夯实基础-JavaScript异步编程

    摘要:调用栈被清空,消息队列中并无任务,线程停止,事件循环结束。不确定的时间点请求返回,将设定好的回调函数放入消息队列。调用栈执行完毕执行消息队列任务。请求并发回调函数执行顺序无法确定。 异步编程 JavaScript中异步编程问题可以说是基础中的重点,也是比较难理解的地方。首先要弄懂的是什么叫异步? 我们的代码在执行的时候是从上到下按顺序执行,一段代码执行了之后才会执行下一段代码,这种方式...

    shadowbook 评论0 收藏0
  • 4.1、异步请求处理(TODO)

    摘要:本部分示例见这个项目的分支下的中引进了基于异步请求处理的。同时主容器线程退出释放并允许处理其他请求。对的调用返回,可以被用于异步处理之上的进一步控制。   本部分示例见这个项目的 mvc 分支下的 AsyncController.java   Spring MVC 3.2 中引进了基于异步请求处理的 Servlet 3。除了返回一个值,一个控制器方法现在可以返回一个java.util...

    AbnerMing 评论0 收藏0
  • JavaScript单线程事件循环(Event Loop)那些事

    摘要:概述本篇主要介绍的运行机制单线程事件循环结论先在中利用运行至完成和非阻塞完成单线程下异步任务的处理就是先处理主模块主线程上的同步任务再处理异步任务异步任务使用事件循环机制完成调度涉及的内容有单线程事件循环同步执行异步执行定时器的事件循环开始 1.概述 本篇主要介绍JavaScript的运行机制:单线程事件循环(Event Loop). 结论先: 在JavaScript中, 利用运行至...

    Shisui 评论0 收藏0
  • 把微信小程序异步API转为Promise,简化异步编程,告别层层回调

    摘要:微信官方没有给出来处理异步操作,而官方异步的又非常多,这使得多异步编程会层层回调,代码一复杂,回调起来就想砸电脑。是一个转换微信小程序异步为的一个工具库优点避免小程序异步编程多次回调带来的过多回调导致逻辑不清晰,篇幅过长等问题。 把微信小程序异步API转化为Promise。用Promise处理异步操作有多方便,谁用谁知道。微信官方没有给出Promise API来处理异步操作,而官方AP...

    antz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<