返回顶部
首页 > 资讯 > 后端开发 > Python >JavaServlet线程中AsyncContext异步处理Http请求
  • 320
分享到

JavaServlet线程中AsyncContext异步处理Http请求

JavaAsyncContext异步处理JavaServletAsyncContext 2023-03-01 11:03:52 320人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录AsyncContextAsyncContext使用示例及测试示例测试结果AsyncContext应用场景背景AsyncContext解决生产问题AsyncContext Asy

AsyncContext

AsyncContextServlet 3.0使Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该Servlet线程。在接收到请求之后,Servlet线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度

Servlet 3.0新增了异步处理,可以先释放容器分配给请求的线程与相关资源,减轻系统负担,原先释放了容器所分配线程的请求,其响应将被延后,可以在处理完成(例如长时间运算完成、所需资源已获得)时再对客户端进行响应。

在Servlet 3.0中,在ServletRequest上提供了startAsync()方法,该方法会根据请求的ServletRequestServletResponse创建AsyncContext对象。

    @Override
    public AsyncContext startAsync() {
        return startAsync(getRequest(),response.getResponse());
    }
    @Override
    public AsyncContext startAsync(ServletRequest request,
            ServletResponse response) {
        if (!isAsyncSupported()) {
            IllegalStateException ise =
                    new IllegalStateException(sm.getString("request.asyncNotSupported"));
            log.warn(sm.getString("coyoteRequest.noAsync",
                    StringUtils.join(getNonAsyncClassNames())), ise);
            throw ise;
        }
        if (asyncContext == null) {
            asyncContext = new AsyncContextImpl(this);
        }
        asyncContext.setStarted(getContext(), request, response,
                request==getRequest() && response==getResponse().getResponse());
        asyncContext.setTimeout(getConnector().getAsyncTimeout());
        return asyncContext;
    }

请求调用startAsyncServlet线程将会被释放,请求交由其他线程去处理,如果业务线程没有处理完,客户端将不会收到响应,直到调用AsyncContextcomplete()dispatch(ServletContext context, String path)方法为止,dispatch方法会根据path进行重定向。AsyncContextImpl大致代码如下:

    @Override
    public void complete() {
        if (log.isDebugEnabled()) {
            logDebug("complete   ");
        }
        check();
        request.getCoyoteRequest().action(ActionCode.ASYNC_COMPLETE, null);
    }
    @Override
    public void dispatch() {
        check();
        String path;
        String cpath;
        ServletRequest servletRequest = getRequest();
        if (servletRequest instanceof httpservletRequest) {
            HttpServletRequest sr = (HttpServletRequest) servletRequest;
            path = sr.getRequestURI();
            cpath = sr.getContextPath();
        } else {
            path = request.getRequestURI();
            cpath = request.getContextPath();
        }
        if (cpath.length() > 1) {
            path = path.substring(cpath.length());
        }
        if (!context.getDispatchersUseEncodedPaths()) {
            path = UDecoder.URLDecode(path, StandardCharsets.UTF_8);
        }
        dispatch(path);
    }

AsyncContext使用示例及测试

示例

设置Tomcat线程数为1

server:
  port: 9099
  servlet:
    context-path: /server/v1
  # 设置Tomcat线程数为1
  tomcat:
    min-spare-threads: 1
    max-threads: 1

Controller

@RestController
public class AsyncTestController {
    private final ScheduledExecutorService timeoutChecker = new ScheduledThreadPoolExecutor(1, threadFactory);
    private static boolean result = false;
    @PostMapping("/async")
    public void async(@RequestBody Request re1, HttpServletRequest request, HttpServletResponse response) {
        // 创建AsyncContext
        AsyncContext asyncContext = request.startAsync(request, response);
        String name = re1.getUsername();
        // 设置处理超时时间2s
        asyncContext.setTimeout(2000L);
        // asyncContext监听
        asyncContext.addListener(new AsyncListener() {
            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException {
            }
            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {
                asyncContext.getResponse().getWriter().print(name + ":timeout");
                asyncContext.complete();
            }
            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException {
            }
            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
            }
        });
        // 定时处理业务,处理成功后asyncContext.complete();完成异步请求
        timeoutChecker.scheduleWithFixedDelay(() -> {
            try {
                if (result) {
                    asyncContext.getResponse().getWriter().print(name);
                    asyncContext.complete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 100L, TimeUnit.MILLISECONDS);
    }
    // 模拟业务处理完成
    @PostMapping("/notify")
    public void notify(Boolean s) {
        result = s;
    }
}

测试结果

  • 测试指标

并发5,两个循环

  • 测试结果

10条并发请求都能够处理,并且处理的时间都是2s左右(因为设置的超时时间是2s),通过该测试结果可以看出,使用AsyncContext可以在容器资源有限的情况下处理更多的请求,这在高并发场景下就比较有用了。

AsyncContext应用场景

使用AsyncContext实现的Http长轮询在许多的中间件的信息同步场景中应用广泛,例如Nacos配置中心和Apache Shenyu网关。

背景

公司一个系统是Netty实现的tcp协议的服务,其中的一个业务是设备请求后台接口查询支付结果,接口的处理逻辑是收到请求后就将请求放到一个队列中,然后由业务线程异步处理,当收到支付结果完成后将响应给客户端支付结果,该接口的超时时间是2s,如果2s查不到支付结果就返回给客户端查不到结果,客户端收到该错误后重新发起查询,直到客户端的整个业务超时。

公司由于服务架构调整,要将该系统改造成基于SpringBoot的Http协议接口,如果”支付结果查询接口“不做机制的变更,就会导致每一次结果查询都会阻塞等待队列中查询支付结果的查询,因为支付是异步的,所以支付结果查询会比较耗时,如果机制不改那么如果并发增大的话会导致服务器的处理请求线程全部被打满,整个服务对于其他请求,其他业务都变得不可用了,这个结果是不可以接受的。

AsyncContext解决生产问题

基于示例中的demo进行业务改造

开启异步,设置整个异步接口处理的超时时间(2s),设置Listener主要用于处理接口超时,阻塞队列处理查询支付结果,查到结果后调用complete完成该长轮询,如果2s没有查到结果,那就返回查询超时,客户端继续轮询。

到此这篇关于Java Servlet线程中AsyncContext异步处理Http请求的文章就介绍到这了,更多相关Java AsyncContext异步处理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaServlet线程中AsyncContext异步处理Http请求

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

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

猜你喜欢
  • JavaServlet线程中AsyncContext异步处理Http请求
    目录AsyncContextAsyncContext使用示例及测试示例测试结果AsyncContext应用场景背景AsyncContext解决生产问题AsyncContext Asy...
    99+
    2023-03-01
    Java AsyncContext异步处理 Java Servlet AsyncContext
  • SpringBoot多线程进行异步请求的处理方式
    目录SpringBoot多线程进行异步请求的处理第一步:编写配置类第二步:对方法使用注解标注为使用多线程进行处理SpringBoot请求线程优化使用Callable来实现1、异步调用...
    99+
    2024-04-02
  • Java 异步编程教程:如何在http请求中使用多线程实现异步编程?
    Java是一种面向对象的编程语言,具有很好的可移植性和可扩展性,在Web开发中广泛应用。然而,由于Web应用程序需要处理大量的http请求,因此必须采用异步编程技术,以确保Web应用程序的性能和可扩展性。 在本文中,我们将介绍如何使用Ja...
    99+
    2023-06-25
    异步编程 教程 http
  • Java 异步编程教程:如何在http请求中实现异步编程?
    随着互联网技术的不断发展,越来越多的应用需要处理大量的网络请求。而在高并发场景下,同步的网络请求会导致线程阻塞,从而降低应用的性能。因此,采用异步编程模式可以有效地提高应用的性能和并发能力。本文将为你介绍如何在Java中实现异步编程,并通...
    99+
    2023-06-25
    异步编程 教程 http
  • ASP应用程序中如何处理异步请求?
    随着互联网技术的不断发展,越来越多的网站需要处理大量的异步请求,以提高网站的性能和用户体验。ASP应用程序也不例外,如何处理异步请求是一个非常重要的问题。本文将介绍ASP应用程序中如何处理异步请求,希望能对ASP开发者有所帮助。 一、什么...
    99+
    2023-07-27
    缓存 shell 异步编程
  • 如何异步请求处理函数
    本篇文章为大家展示了如何异步请求处理函数,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。sendmail.php代码如下:<php$name = $_POST[...
    99+
    2024-04-02
  • python中异步IO怎么同时处理请求
    小编给大家分享一下python中异步IO怎么同时处理请求,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!python主要应用领域有哪些1、云计算,典型应用OpenS...
    99+
    2023-06-14
  • RocketMQ怎么实现请求异步处理
    这篇文章主要介绍“RocketMQ怎么实现请求异步处理”,在日常操作中,相信很多人在RocketMQ怎么实现请求异步处理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”RocketMQ怎么实现请求异步处理”的疑...
    99+
    2023-06-19
  • PHP开发中如何处理异步请求和并发处理
    在Web开发中,经常会遇到需要处理大量并发请求和异步请求的情况。以PHP为例,我们可以利用一些技术和工具来处理这些需求,提高系统的性能和响应能力。本文将介绍如何处理异步请求和并发处理,并提供一些具体的代码示例。一、异步请求的处理使用Ajax...
    99+
    2023-10-21
    异步请求 PHP开发 并发处理
  • PHP中的HTTP请求与响应处理
    PHP是一门脚本语言,常用于Web开发。在Web开发中,HTTP协议是重要的组成部分。对于PHP开发者来说,了解如何发送HTTP请求和处理HTTP响应是必要的技能之一。在本文中,我们将介绍PHP中的HTTP请求和响应处理。发送HTTP请求在...
    99+
    2023-05-23
    HTTP 请求 响应
  • python处理http请求中特殊字符(
    直接看代码吧# encoding:utf-8from urllib.parse import quoteimport urllib.requestimport stringimport jsonurl = quote('http://tes...
    99+
    2023-01-31
    特殊字符 python http
  • PHP中如何处理HTTP请求错误?
    在Web开发中,HTTP请求错误是时常会碰到的问题。可能是接口请求超时、参数传递错误、网络连接不正常等等。在PHP中,我们可以通过各种方法处理这些HTTP请求错误。下面就来具体探讨一下。一、使用try…catch语句使用try…catch语...
    99+
    2023-12-09
    Http请求 PHP 错误处理
  • ASP.NET处理HTTP请求的流程是什么
    这篇文章主要介绍“ASP.NET处理HTTP请求的流程是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ASP.NET处理HTTP请求的流程是什么”文章能帮助大家解决问题。一、ASP.NET处理管...
    99+
    2023-06-30
  • django异步请求处理的方法是什么
    Django中的异步请求处理可以通过以下几种方法实现:1. 使用Django的内置异步任务处理机制:Django提供了一个名为`as...
    99+
    2023-09-26
    Django
  • Node.js 事件循环如何处理异步请求
    ...
    99+
    2024-04-02
  • Java中出现HTTP请求超时如何处理
    这篇文章给大家介绍Java中出现HTTP请求超时如何处理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在发送POST或GET请求时,返回超时异常处理办法:捕获 SocketTimeoutException | Conn...
    99+
    2023-06-14
  • 微信小程序中es6-promise.js封装请求与处理异步进程的方法
    这篇文章主要介绍“微信小程序中es6-promise.js封装请求与处理异步进程的方法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“微信小程序中es6-promise.js封装请求与处理异步进程的方...
    99+
    2023-06-17
  • Python并发编程:如何优化HTTP请求处理?
    随着互联网的发展,我们的应用程序越来越依赖于HTTP请求。无论是爬取网页、请求API接口还是处理数据,HTTP请求几乎成为了每一个应用程序的必要操作。然而,如果我们在处理HTTP请求时没有考虑并发处理,那么我们的程序可能会因为等待服务器响...
    99+
    2023-09-21
    http 二维码 并发
  • Tomcat处理请求的线程模型详解
    目录一、前言二、tomcat结构三、探讨tomcat是如何处理请求1、初始化2、如何处理客户端请求总结一、前言 JAVA后端项目,运行在容器tomcat中,由于现在springboo...
    99+
    2024-04-02
  • axios异步请求的流程与原理是什么
    这篇文章主要介绍了axios异步请求的流程与原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇axios异步请求的流程与原理是什么文章都会有所收获,下面我们一起来看看吧。...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作