异步Servlet特性

编程

 1.需要解决的问题

  • 1.为什么使用异步Servlet? 同步Servlet阻塞了什么
  • 2.异步Servlet编写流程

 2.同步Servlet

 同步Servlet是指 tomcat线程去执行 servlet方法后,会一直被阻塞,直到业务代码执行完毕 ,这样tomcat 吞吐量就有限

 直接看代码,应该都很熟悉 同步Servlet的开发吧,

/**

* 同步Servlet 样例

* [@author](https://my.oschina.net/arthor) johnny

*/

@WebServlet(name = "Sync-SyncServlet", urlPatterns = "/sync")

[@Slf4j](https://my.oschina.net/slf4j)

public class SyncServlet extends HttpServlet {

[@Override](https://my.oschina.net/u/1162528)

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

log.info("doPost sync servlet");

}

[@Override](https://my.oschina.net/u/1162528)

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

long start = System.currentTimeMillis();

try {

//模拟业务代码处理

TimeUnit.SECONDS.sleep(3);

} catch (InterruptedException e) {

e.printStackTrace();

}

long end = System.currentTimeMillis();

log.info("doGet sync servlet 耗时: {} 秒", (end - start) / 1000);

}

}

 3.异步Servlet

 异步Servlet主要是要注意

  • 1.开启异步Servlet asyncSupported = true

  • 2.获取异步上下文 AsyncContext asyncContext = request.startAsync();

  • 3.将业务耗时方法放入 线程池中去异步执行 注意需要传入异步上下文,供业务方法内部调用,如

      CompletableFuture.runAsync(() -> {

    doSomeThing(asyncContext, asyncContext.getRequest(), asyncContext.getResponse());

    });

  • 4.业务方法调用上下文结束 asyncContext.complete();

      /**

    * 异步Servlet 案例

    *

    * @author johnny

    * <p>

    * asyncSupported = true 表示开启异步支持

    */

    @WebServlet(name = "AsyncServlet",

    asyncSupported = true,

    urlPatterns = "/async")

    @Slf4j

    public class AsyncServlet extends HttpServlet {

    @Override

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    log.info("【doPost async Servlet 】");

    }

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    long start = System.currentTimeMillis();

    //获取异步上下文

    AsyncContext asyncContext = request.startAsync();

    //使用java8的 CompletableFuture,将任务放到线程池中去执行

    CompletableFuture.runAsync(() -> {

    doSomeThing(asyncContext, asyncContext.getRequest(), asyncContext.getResponse());

    });

    long end = System.currentTimeMillis();

    log.info("【doGet async Servlet 耗时 {} 】", (end - start));

    }

    private void doSomeThing(AsyncContext asyncContext, ServletRequest request, ServletResponse response) {

    //执行业务代码

    try {

    TimeUnit.SECONDS.sleep(3);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    //告诉异步上下文 结束了

    asyncContext.complete();

    }

    }

 浏览器访问

http://localhost:8080/async

 可以看到日志,该Servlet仅仅只耗时 7毫秒,这样tomcat 调用这个Servlet得线程 又可以去处理其他请求,从而增加了吞吐量,

 这就是异步Servlet的作用

 4.解答问题:为什么使用异步Servlet? 同步Servlet阻塞了什么

 拿Tomcat服务器为例,当请求到达时候,Tomcat服务器会为每个请求创建一个线程,然后调用对应的Servlet的doGet或doPost方法,如果在该Servlet 的doPost 或者 doGet 方法中有业务耗时操作,则该线程会一直等待,直到业务逻辑处理完成才会把对应的 线程收回到Tomcat 重新接收请求

 而异步Servelt的目的就是 不用Tomcat的线程去等待,直接将其返回去接收其他请求,使用异步Servlet的支持 可以把耗时操作放入线程池中当执行完毕后 通知异步上下文去返回结果给前端 ,所以前端的反应其实看不出来什么效果,但是后台会有很大差异

 5.疑问

  5.1 使用SpringMVC 怎么使用异步

  看到这里肯定有人会问,现在谁还会去用Servlet去编程,都是用SpringMvc去编程了,当然SpringMvc早在3.2的版本中就已经对异步Servlet进行了支持,到现在已经提供了3中方式去实现异步

  • DeferredResult
  • Callable
  • CompletionStage/CompletableFuture

  详细使用教程后期会再写一篇,关于SpringMVC对异步Servlet的支持!

  5.2 有了SpringMVC 的异步支持 为什么还需要 Spring5提供的 WebFlux

  其实SpringMvc支持的异步已经能够满足我们的基本开发需要,那么为什么Spring还要引入 WebFlux 技术栈,

就是 一种趋势,并发编程模型已经成趋势

 6.总结

 本篇主要讲解 如何使用 异步Servlet的处理请求,并且演示 同步Servlet和异步Servlet的区别,以及异步Servlet带来哪些好处。

 涉及的同步Servlet会带来的问题,并且简单聊了下SpringMVC里对异步Servlet的支持,等等。。

后续会编写一篇关于SpringMVC对异步Servlet支持的详细教程,其实底层就是异步Servlet的使用 加油!!

个人博客系统:https://www.askajohnny.com 欢迎访问!

本文由博客一文多发平台 OpenWrite 发布!

以上是 异步Servlet特性 的全部内容, 来源链接: utcz.com/z/513985.html

回到顶部