高性能的关键异步请求的原生态

本文深入讲解了异步请求的概念及其实现方式,对比了同步请求的局限性,并详细介绍了Servlet3.0中异步请求的处理流程,包括开启异步支持、异步请求代码书写以及异步监听器的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文作者:黄少存,叩丁狼高级讲师。原创文章,转载请注明出处。

前言:说到异步请求咱们得先知道何为同步请求,从而对比来理解异步请求.同步请求简述, 浏览器发送请求->web服务器开启线程处理请求->处理完把结果返回给浏览器. 咱们来看下程序中同步请求的业务逻辑图.

同步请求

对于同步操作来说,web服务器开启请求处理线程之后需要等待业务的处理完成才能做响应.对于同步请求来说这是理所当然的事情. 一般这样的操作也足够.但是如果有特殊要求,比如高并发,处理业务时间长的操作比较多,那会出现什么问题呢?

由于请求处理线程的总数是有限的,以上特殊请求会出现请求线程不够用的请求,因为可能都处于阻塞状态,影响服务器的吞吐量.所以就得使用异步请求,这也是高性能的关键.

异步请求

对于异步请求操作来说,web 服务器的请求处理线程在处理请求上大大减少了时间,仅仅是接收了请求之后唤醒了新的业务处理线程,然后就结束了.这样的话,请求处理线程就可以留出多余的时间去处理其他的请求.提高了服务器的吞吐量.

既然异步请求可以提高处理能力,那如何实现异步请求呢?

其实 jetty 服务器就实现了异步请求,只是那是比较早期的操作了,现在有些框架也是有异步模块的,比如 spring mvc,但在 JavaWeb 中,其最根本的还是 Servlet3.0 的异步请求规范.接下来咱们就来看下servlet 原生态的异步请求实现.

servlet 原生态异步请求

步骤:

  1. 开启异步请求支持
  2. 异步请求代码书写
开启异步请求支持

开启异步请求支持有两种方式.

  1. 通过注解 asyncSupported=true 来实现
  2. 通过 web.xml 配置true来实现
  3. 异步请求监听
异步请求代码书写
// 配置资源路径和开启异步请求支持
@WebServlet(urlPatterns = {"/async"}, asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");

        //获取异步请求上下文对象
        AsyncContext async = req.startAsync();
        // 设置异步处理超时时间,默认30秒
        async.setTimeout(40 * 1000);

        // 启动异步处理,关键操作
        async.start(() -> {
            try {
                // 模拟业务处理耗时
                Thread.sleep(10 * 1000);
                req.setAttribute("msg", "异步处理后的数据" + new Date().toLocaleString());
                // 将请求转发到 index.jsp 页面
                async.dispatch("/async.jsp");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 直接显示到页面的数据,不需等待以上业务处理
        System.out.println("请求处理线程释放:" + new Date().toLocaleString());
    }
}

async.jsp 页面书写

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>异步请求</title>
</head>
<body>
    <a href="/async">发起请求</a><br/>
    异步请求数据: ${msg}
</body>
</html>

最终看到的结果

异步请求监听器接口AsyncListener

Servlet 3.0 为异步处理提供了一个监听器,使用 AsyncListener 接口表示。此接口负责管理异步事件,它可以监控如下四种事件:

  1. 异步线程开始时,调用AsyncListener的onStartAsync(AsyncEvent event)方法;
  2. 异步线程出错时,调用AsyncListener的onError(AsyncEvent event)方法;
  3. 异步线程执行超时,则调用AsyncListener的onTimeout(AsyncEvent event)方法;
  4. 异步执行完毕时,调用AsyncListener的onComplete(AsyncEvent event)方法;
// 配置资源路径和开启异步请求支持
@WebServlet(urlPatterns = {"/async"}, asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        //获取异步请求上下文对象
        AsyncContext async = req.startAsync();
        async.addListener(new MyAsyncListener());

        //...
}
public class MyAsyncListener implements AsyncListener {
    public void onComplete(AsyncEvent event) throws IOException {
        System.out.println("完成后清理操作等..");
    }
    public void onTimeout(AsyncEvent event) throws IOException {
        System.out.println("超时处理..");
    }
    public void onError(AsyncEvent event) throws IOException {
    }
    public void onStartAsync(AsyncEvent event) throws IOException {
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值