最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Servlet線程中AsyncContext異步處理Http請求

 更新時(shí)間:2023年03月01日 10:57:33   作者:Redick01  
這篇文章主要介紹了Java Servlet線程中AsyncContext異步處理Http請求及在業(yè)務(wù)中應(yīng)用,AsyncContext是Servlet 3.0使Servlet 線程不再需要一直阻塞,直到業(yè)務(wù)處理完畢才能再輸出響應(yīng),最后才結(jié)束該Servlet線程

AsyncContext

AsyncContextServlet 3.0使Servlet 線程不再需要一直阻塞,直到業(yè)務(wù)處理完畢才能再輸出響應(yīng),最后才結(jié)束該Servlet線程。在接收到請求之后,Servlet線程可以將耗時(shí)的操作委派給另一個(gè)線程來完成,自己在不生成響應(yīng)的情況下返回至容器。針對(duì)業(yè)務(wù)處理較耗時(shí)的情況,這將大大減少服務(wù)器資源的占用,并且提高并發(fā)處理速度

Servlet 3.0新增了異步處理,可以先釋放容器分配給請求的線程與相關(guān)資源,減輕系統(tǒng)負(fù)擔(dān),原先釋放了容器所分配線程的請求,其響應(yīng)將被延后,可以在處理完成(例如長時(shí)間運(yùn)算完成、所需資源已獲得)時(shí)再對(duì)客戶端進(jìn)行響應(yīng)。

在Servlet 3.0中,在ServletRequest上提供了startAsync()方法,該方法會(huì)根據(jù)請求的ServletRequestServletResponse創(chuàng)建AsyncContext對(duì)象。

    @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;
    }

請求調(diào)用startAsyncServlet線程將會(huì)被釋放,請求交由其他線程去處理,如果業(yè)務(wù)線程沒有處理完,客戶端將不會(huì)收到響應(yīng),直到調(diào)用AsyncContextcomplete()dispatch(ServletContext context, String path)方法為止,dispatch方法會(huì)根據(jù)path進(jìn)行重定向。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使用示例及測試

示例

設(shè)置Tomcat線程數(shù)為1

server:
  port: 9099
  servlet:
    context-path: /server/v1
  # 設(shè)置Tomcat線程數(shù)為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) {
        // 創(chuàng)建AsyncContext
        AsyncContext asyncContext = request.startAsync(request, response);
        String name = re1.getUsername();
        // 設(shè)置處理超時(shí)時(shí)間2s
        asyncContext.setTimeout(2000L);
        // asyncContext監(jiān)聽
        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 {
            }
        });
        // 定時(shí)處理業(yè)務(wù),處理成功后asyncContext.complete();完成異步請求
        timeoutChecker.scheduleWithFixedDelay(() -> {
            try {
                if (result) {
                    asyncContext.getResponse().getWriter().print(name);
                    asyncContext.complete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 100L, TimeUnit.MILLISECONDS);
    }
    // 模擬業(yè)務(wù)處理完成
    @PostMapping("/notify")
    public void notify(Boolean s) {
        result = s;
    }
}

測試結(jié)果

  • 測試指標(biāo)

并發(fā)5,兩個(gè)循環(huán)

  • 測試結(jié)果

10條并發(fā)請求都能夠處理,并且處理的時(shí)間都是2s左右(因?yàn)樵O(shè)置的超時(shí)時(shí)間是2s),通過該測試結(jié)果可以看出,使用AsyncContext可以在容器資源有限的情況下處理更多的請求,這在高并發(fā)場景下就比較有用了。

AsyncContext應(yīng)用場景

使用AsyncContext實(shí)現(xiàn)的Http長輪詢在許多的中間件的信息同步場景中應(yīng)用廣泛,例如Nacos配置中心和Apache Shenyu網(wǎng)關(guān)。

背景

公司一個(gè)系統(tǒng)是Netty實(shí)現(xiàn)的TCP協(xié)議的服務(wù),其中的一個(gè)業(yè)務(wù)是設(shè)備請求后臺(tái)接口查詢支付結(jié)果,接口的處理邏輯是收到請求后就將請求放到一個(gè)隊(duì)列中,然后由業(yè)務(wù)線程異步處理,當(dāng)收到支付結(jié)果完成后將響應(yīng)給客戶端支付結(jié)果,該接口的超時(shí)時(shí)間是2s,如果2s查不到支付結(jié)果就返回給客戶端查不到結(jié)果,客戶端收到該錯(cuò)誤后重新發(fā)起查詢,直到客戶端的整個(gè)業(yè)務(wù)超時(shí)。

公司由于服務(wù)架構(gòu)調(diào)整,要將該系統(tǒng)改造成基于SpringBoot的Http協(xié)議接口,如果”支付結(jié)果查詢接口“不做機(jī)制的變更,就會(huì)導(dǎo)致每一次結(jié)果查詢都會(huì)阻塞等待隊(duì)列中查詢支付結(jié)果的查詢,因?yàn)橹Ц妒钱惒降模灾Ц督Y(jié)果查詢會(huì)比較耗時(shí),如果機(jī)制不改那么如果并發(fā)增大的話會(huì)導(dǎo)致服務(wù)器的處理請求線程全部被打滿,整個(gè)服務(wù)對(duì)于其他請求,其他業(yè)務(wù)都變得不可用了,這個(gè)結(jié)果是不可以接受的。

AsyncContext解決生產(chǎn)問題

基于示例中的demo進(jìn)行業(yè)務(wù)改造

開啟異步,設(shè)置整個(gè)異步接口處理的超時(shí)時(shí)間(2s),設(shè)置Listener主要用于處理接口超時(shí),阻塞隊(duì)列處理查詢支付結(jié)果,查到結(jié)果后調(diào)用complete完成該長輪詢,如果2s沒有查到結(jié)果,那就返回查詢超時(shí),客戶端繼續(xù)輪詢。

到此這篇關(guān)于Java Servlet線程中AsyncContext異步處理Http請求的文章就介紹到這了,更多相關(guān)Java AsyncContext異步處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分析ThreadLocal內(nèi)存泄漏問題

    分析ThreadLocal內(nèi)存泄漏問題

    ThreadLocal的作用是提供線程內(nèi)的局部變量,這種變量在線程生命周期內(nèi)起作用,減少同一個(gè)線程內(nèi)多個(gè)函數(shù)或者組件之間一些公共變量傳遞的復(fù)雜度,但是如果濫用ThreadLocal可能會(huì)導(dǎo)致內(nèi)存泄漏,所以本文將為大家分析ThreadLocal內(nèi)存泄漏問題
    2023-07-07
  • Java實(shí)現(xiàn)五子棋(附詳細(xì)源碼)

    Java實(shí)現(xiàn)五子棋(附詳細(xì)源碼)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Spring Data JDBC介紹及實(shí)現(xiàn)代碼

    Spring Data JDBC介紹及實(shí)現(xiàn)代碼

    這篇文章主要介紹了Spring Data JDBC介紹及實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • Java中BorderLayout布局管理器的兩種排列方式

    Java中BorderLayout布局管理器的兩種排列方式

    這篇文章主要介紹了Java中BorderLayout布局管理器的兩種排列方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot配置Access-Control-Allow-Origin教程

    SpringBoot配置Access-Control-Allow-Origin教程

    文章介紹了三種配置Spring Boot跨域訪問的方法:1. 使用過濾器;2. 在WebConfig配置文件中設(shè)置;3. 通過注解配置,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)讀者支持腳本之家
    2025-03-03
  • SpringBoot使用Sa-Token實(shí)現(xiàn)登錄認(rèn)證

    SpringBoot使用Sa-Token實(shí)現(xiàn)登錄認(rèn)證

    本文主要介紹了SpringBoot使用Sa-Token實(shí)現(xiàn)登錄認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 基于mybatis 動(dòng)態(tài)SQL查詢總結(jié)

    基于mybatis 動(dòng)態(tài)SQL查詢總結(jié)

    這篇文章主要介紹了mybatis 動(dòng)態(tài)SQL查詢總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 在Spring框架下配置Quartz集群的詳細(xì)步驟(MySQL數(shù)據(jù)源)

    在Spring框架下配置Quartz集群的詳細(xì)步驟(MySQL數(shù)據(jù)源)

    Quartz 是一個(gè)功能強(qiáng)大的調(diào)度庫,可以在 Java 應(yīng)用中用于執(zhí)行定時(shí)任務(wù),本文將介紹如何在 Spring 框架下配置 Quartz 集群,并使用 MySQL 作為數(shù)據(jù)源來存儲(chǔ)調(diào)度信息,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2025-01-01
  • JAVA實(shí)現(xiàn)鏈表面試題

    JAVA實(shí)現(xiàn)鏈表面試題

    這篇文章主要為大家詳細(xì)介紹了JAVA相關(guān)實(shí)現(xiàn)鏈表的面試題,代碼實(shí)現(xiàn)非常詳細(xì),每一個(gè)方法講解也很到位,特別適合參加Java面試的朋友閱讀
    2015-09-09
  • 使用Spring的FactoryBean創(chuàng)建和獲取Bean對(duì)象方式

    使用Spring的FactoryBean創(chuàng)建和獲取Bean對(duì)象方式

    這篇文章主要介紹了使用Spring的FactoryBean創(chuàng)建和獲取Bean對(duì)象方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03

最新評(píng)論

法库县| 伊川县| 体育| 天祝| 大英县| 堆龙德庆县| 兰坪| 福安市| 舟曲县| 嘉祥县| 朝阳县| 开封县| 安康市| 黑河市| 瓮安县| 嘉兴市| 西平县| 昌都县| 张掖市| 金华市| 祁东县| 礼泉县| 保德县| 太谷县| 凌源市| 昔阳县| 新宾| 东乌珠穆沁旗| 云南省| 新龙县| 汉中市| 龙山县| 海盐县| 镇宁| 德昌县| 中方县| 宜兴市| 邻水| 沐川县| 沛县| 昌宁县|