广告
返回顶部
首页 > 资讯 > 精选 >Java中Servelt3异步请求方式是什么
  • 106
分享到

Java中Servelt3异步请求方式是什么

2023-06-16 13:06:09 106人浏览 泡泡鱼
摘要

本篇内容介绍了“Java中Servelt3异步请求方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!用同步请求模型,所有动作都交给同一

本篇内容介绍了“Java中Servelt3异步请求方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

用同步请求模型,所有动作都交给同一个 Tomcat 线程处理,所有动作处理完成,线程才会被释放回线程池

想象一下如果业务需要较长时间处理,那么这个 Tomcat 线程其实一直在被占用,随着请求越来越多,可用 I/O  线程越来越少,直到被耗尽。这时后续请求只能等待空闲 Tomcat 线程,这将会加长了请求执行时间。

如果客户端不关心返回业务结果,这时我们可以自定义线程池,将请求任务提交给线程池,然后立刻返回。

也可以使用 spring Async 任务,大家感兴趣可以自行查找一下资料

但是很多场景下,客户端需要处理返回结果,我们没办法使用上面的方案。在 Servlet2 时代,我们没办法优化上面的方案。

不过等到 Servlet3 ,引入异步 Servlet 新特性,可以完美解决上面的需求。

异步 Servlet 执行请求流程:

将请求信息解析为 httpservletRequest

分发到具体 Servlet 处理,将业务提交给自定义业务线程池,请求立刻返回,Tomcat 线程立刻被释放

当业务线程将任务执行结束,将会将结果转交给 Tomcat 线程

通过 HttpServletResponse 将响应结果返回给等待客户端

引入异步 Servlet3 整体流程如下:

Java中Servelt3异步请求方式是什么

使用异步 Servelt,Tomcat 线程仅仅处理请求解析动作,所有耗时较长的业务操作全部交给业务线程池,所以相比同步请求, Tomcat 线程可以处理  更多请求。

虽然我们将业务处理交给业务线程池异步处理,但是对于客户端来讲,其还在同步等待响应结果。

可能有些同学会觉得异步请求将会获得更快响应时间,其实不是的,相反可能由于引入了更多线程,增加线程上下文切换时间。

虽然没有降低响应时间,但是通过请求异步化带来其他明显优点:

  • 可以处理更高并发连接数,提高系统整体吞吐量

  • 请求解析与业务处理完全分离,职责单一

  • 自定义业务线程池,我们可以更容易对其监控,降级等处理

  • 可以根据不同业务,自定义不同线程池,相互隔离,不用互相影响

所以具体使用过程,我们还需要进行的相应的压测,观察响应时间以及吞吐量等其他指标,综合选择。

异步 Servelt 使用方式

异步 Servelt 使用方式不是很难,阿粉总结就是下面三板斧:

  1. HttpServletRequest#startAsync 获取 AsyncContext 异步上下文对象

  2. 使用自定义的业务线程池处理业务逻辑

  3. 业务线程处理结束,通过 AsyncContext#complete 返回响应结果

下面的例子将会使用 SpringBootWEB 容器选择 Tomcat

示例代码如下:

ExecutorService executorService = Executors.newFixedThreadPool(10);  @RequestMapping("/hello") public void hello(HttpServletRequest request) {     AsyncContext asyncContext = request.startAsync();     // 超时时间     asyncContext.setTimeout(10000);     executorService.submit(() -> {         try {             // 休眠 5s,模拟业务操作             TimeUnit.SECONDS.sleep(5);             // 输出响应结果             asyncContext.getResponse().getWriter().println("hello world");             log.info("异步线程处理结束");         } catch (Exception e) {             e.printStackTrace();         } finally {             asyncContext.complete();         }     });     log.info("servlet 线程处理结束"); }

浏览器访问该请求将会同步等待 5s 得到输出响应,应用日志输出结果如下:

2020-03-24 07:27:08.997  INFO 79257 --- [NIO-8087-exec-4] com.xxxx   : servlet 线程处理结束 2020-03-24 07:27:13.998  INFO 79257 --- [pool-1-thread-3] com.xxxx   : 异步线程处理结束

这里我们需要注意设置合理的超时时间,防止客户端长时间等待。

SpringMVC

Servlet3 api ,无法使用 springMVC 为我们提供的特性,我们需要自己处理响应信息,处理方式相对繁琐。

Springmvc 3.2 基于 Servelt3 引入异步请求处理方式,我们可以跟使用同步请求一样,方便使用异步请求。

SpringMVC 提供有两种异步方式,只要将 Controller 方法返回值修改下述类即可:

  • DeferredResult

  • Callable

DeferredResult

DeferredResult 是 SpringMVC 3.2  之后引入新的类,只要让请求方法返回DeferredResult,就可以快速使用异步请求,示例代码如下:

ExecutorService executorService = Executors.newFixedThreadPool(10);  @RequestMapping("/hello_v1") public DeferredResult<String> hello_v1() {     // 设置超时时间     DeferredResult<String> deferredResult = new DeferredResult<>(7000L);     // 异步线程处理结束,将会执行该回调方法     deferredResult.onCompletion(() -> {         log.info("异步线程处理结束");     });     // 如果异步线程执行时间超过设置超时时间,将会执行该回调方法     deferredResult.onTimeout(() -> {         log.info("异步线程超时");         // 设置返回结果         deferredResult.setErrorResult("timeout error");     });     deferredResult.onError(throwable -> {         log.error("异常", throwable);         // 设置返回结果         deferredResult.setErrorResult("other error");     });     executorService.submit(() -> {         try {             TimeUnit.SECONDS.sleep(5);             deferredResult.setResult("hello_v1");             // 设置返回结果         } catch (Exception e) {             e.printStackTrace();             // 若异步方法内部异常             deferredResult.setErrorResult("error");         }     });     log.info("servlet 线程处理结束");     return deferredResult;  }

创建 DeferredResult 实例时可以传入特定超时时间。另外我们可以设置默认超时时间:

# 异步请求超时时间 spring.mvc.async.request-timeout=2000

如果异步程序执行完成,可以调用 DeferredResult#setResult返回响应结果。此时若有设置  DeferredResult#onCompletion 回调方法,将会触发该回调方法。

同时我们还可以设置超时回调方法 DeferredResult#onTimeout,一旦异步线程执行超时,将会触发该回调方法。

最后 DeferredResult 还提供其他异常的回调方法  onError,起初阿粉以为只要异步线程内发生异常,就会触发该回调方法。尝试在异步线程内抛出异常,但是无法成功触发。

后续阿粉查看这个方法的 doc,当 web 容器线程处理异步请求时发生异常,才能成功触发。

 Java中Servelt3异步请求方式是什么

Callable

Spring 另外还提供一种异步请求使用方式,直接使用 jdk Callable。示例代码如下:

@RequestMapping("/hello_v2") public Callable<String> hello_v2() {     return new Callable<String>() {         @Override         public String call() throws Exception {             TimeUnit.SECONDS.sleep(5);             log.info("异步方法结束");             return "hello_v2";         }     }; }

默认情况下,直接执行将会输出 WARN 日志

Java中Servelt3异步请求方式是什么

这是因为默认情况使用 SimpleAsyncTaskExecutor  执行异步请求,每次调用执行都将会新建线程。由于这种方式不复用线程,生产不推荐使用这种方式,所以我们需要使用线程池代替。

我们可以使用如下方式自定义线程池:

@Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) public AsyncTaskExecutor executor() {     ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();     threadPoolTaskExecutor.setThreadNamePrefix("test-");     threadPoolTaskExecutor.setCorePoolSize(10);     threadPoolTaskExecutor.setMaxPoolSize(20);     return threadPoolTaskExecutor; }

注意 Bean 名称一定要是 applicationTaskExecutor,若不一致, Spring 将不会使用自定义线程池。

或者可以直接使用 SpringBoot 配置文件方式配置代替:

# 核心线程数 spring.task.execution.pool.core-size=10 # 最大线程数 spring.task.execution.pool.max-size=20 # 线程名前缀 spring.task.execution.thread-name-prefix=test # 还有另外一些配置,读者们可以自行配置

这种方式异步请求的超时时间只能通过配置文件方式配置。

spring.mvc.async.request-timeout=10000

如果需要为单独请求的配置特定的超时时间,我们需要使用 WebAsyncTask 包装 Callable 。

@RequestMapping("/hello_v3") public WebAsyncTask<String> hello_v3() {     System.out.println("asdas");     Callable<String> callable=new Callable<String>() {         @Override         public String call() throws Exception {             TimeUnit.SECONDS.sleep(5);             log.info("异步方法结束");             return "hello_v3";         }     };     // 单位 ms     WebAsyncTask<String> webAsyncTask=new WebAsyncTask<>(10000,callable);     return webAsyncTask; }

“Java中Servelt3异步请求方式是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Java中Servelt3异步请求方式是什么

本文链接: https://www.lsjlt.com/news/283827.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中Servelt3异步请求方式是什么
    本篇内容介绍了“Java中Servelt3异步请求方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!用同步请求模型,所有动作都交给同一...
    99+
    2023-06-16
  • AJAX中请求方式以及同步异步有什么区别
    这篇文章主要介绍AJAX中请求方式以及同步异步有什么区别,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 请求方式,分为GET与POST: GET 最为常...
    99+
    2022-10-19
  • Spring中注解方式的异步请求
    一、Servlet3.0异步请求 @WebServlet(value = "/async", asyncSupported = true) public class HelloA...
    99+
    2022-11-12
  • react异步请求数据的方法是什么
    在React中,常用的异步请求数据的方法有以下几种:1. 使用fetch API:fetch是现代浏览器提供的一种用于进行网络请求的...
    99+
    2023-08-19
    react
  • django异步请求处理的方法是什么
    Django中的异步请求处理可以通过以下几种方法实现:1. 使用Django的内置异步任务处理机制:Django提供了一个名为`as...
    99+
    2023-09-26
    Django
  • php协程异步请求的方法是什么
    PHP协程是一种并发编程的方式,可以通过异步请求来实现。在PHP中,可以使用swoole扩展来实现协程异步请求。 下面是一个使用sw...
    99+
    2023-10-27
    php
  • java中怎么异步请求网络
    本篇文章给大家分享的是有关java中怎么异步请求网络,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。java怎么实现异步请求网络,这里实现思路有很多种,但是我们这里有个比较方便的...
    99+
    2023-06-02
  • jquery异步请求的概念是什么
    本篇内容主要讲解“jquery异步请求的概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“jquery异步请求的概念是什么”吧! ...
    99+
    2022-10-19
  • es6异步请求三个状态是什么
    本教程操作环境:windows7系统、ECMAScript 6版、Dell G3电脑。Promise 是异步编程的一种解决方案:1、主要用于异步计算2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果3、可以在对象之间传递和操作...
    99+
    2023-05-14
    promise ES6 异步
  • Spring中注解方式的异步请求如何实现
    小编给大家分享一下Spring中注解方式的异步请求如何实现,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、Servlet3.0异步请求@WebServlet(value = "/async&...
    99+
    2023-06-15
  • vue axios中的get请求方式是什么
    这篇文章主要讲解了“vue axios中的get请求方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue axios中的get请求方式是什么”吧!vue axi...
    99+
    2023-07-02
  • axios异步请求的流程与原理是什么
    这篇文章主要介绍了axios异步请求的流程与原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇axios异步请求的流程与原理是什么文章都会有所收获,下面我们一起来看看吧。...
    99+
    2022-10-19
  • 了解HTTP请求:Java和Bash中的差异是什么?
    HTTP请求是Web开发中必不可少的一部分。Java和Bash是两种常用的编程语言,它们都可以用来发送HTTP请求。然而,它们之间还是存在一些差异的。本文将介绍HTTP请求在Java和Bash中的差异,并通过演示代码来帮助读者更好地理解。 ...
    99+
    2023-08-15
    path bash http
  • uniapp封装发送请求方式是什么
    随着前端开发的不断发展,前端框架也越来越丰富多样。而其中,uni-app框架的崛起引起了前端开发者的广泛关注。因为它具有了很多原生开发中才有的功能,如无需反复打包、多端发布等。在uni-app开发过程中,我们常常需要进行网络请求。而为了方便...
    99+
    2023-05-14
  • java设置请求头的方法是什么
    在Java中设置请求头的方法是通过调用URLConnection对象的setRequestProperty()方法来实现的。 例如,...
    99+
    2023-10-25
    java
  • Rust异步编程方式是什么
    这篇文章主要讲解了“Rust异步编程方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Rust异步编程方式是什么”吧!调度器是如何工作的调度器,顾名思...
    99+
    2022-10-19
  • java异步转同步的方法是什么
    Java中实现异步转同步的方法有多种,下面列举了几种常用的方法。 使用CountDownLatch: CountDownLatch...
    99+
    2023-10-24
    java
  • vue中异步数据获取方式是什么
    今天给大家介绍一下vue中异步数据获取方式是什么。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。vue中异步数据获取1、获取异步数据,通过async/await...
    99+
    2023-06-28
  • Feign的请求和响应日志方式是什么
    这篇文章主要介绍了Feign的请求和响应日志方式是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Feign的请求和响应日志方式是什么文章都会有所收获,下面我们一起来看看吧。1、项目里定义FeignClien...
    99+
    2023-07-02
  • Java中异步编程的关键字和存储方式是什么?
    随着互联网的普及和应用场景的不断扩大,异步编程逐渐成为开发人员必须掌握的技能之一。Java作为一门流行的编程语言,也支持异步编程。在本文中,我们将探讨Java中异步编程的关键字和存储方式。 一、异步编程的概念 异步编程是一种编程方式,其中...
    99+
    2023-07-25
    异步编程 关键字 存储
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作