异步Servlet
本篇主要讲解 如何使用 异步Servlet的处理请求,并且演示 同步Servlet和异步Servlet的区别,以及异步Servlet带来哪些好处 。
1.需要解决的问题
- 1.为什么使用异步Servlet? 同步Servlet阻塞了什么
- 2.异步Servlet编写流程
2.同步Servlet
同步Servlet是指 tomcat线程去执行 servlet方法后,会一直被阻塞,直到业务代码执行完毕 ,这样tomcat 吞吐量就有限
直接看代码,应该都很熟悉 同步Servlet的开发吧,
/**
* 同步Servlet 样例
* @author johnny
*/
@WebServlet(name = "Sync-SyncServlet", urlPatterns = "/sync")
@Slf4j
public class SyncServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.info("doPost sync servlet");
}
@Override
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);
}
}
Xnip20200225_161959.png
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 发布!
网友评论