欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

AsyncContext

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

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

在Servlet 3.0中,在ServletRequest上提供了startAsync()方法,該方法會根據(jù)請求的ServletRequestServletResponse創(chuàng)建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;
    }

請求調(diào)用startAsyncServlet線程將會被釋放,請求交由其他線程去處理,如果業(yè)務線程沒有處理完,客戶端將不會收到響應,直到調(diào)用AsyncContextcomplete()dispatch(ServletContext context, String path)方法為止,dispatch方法會根據(jù)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線程數(shù)為1

server:
  port: 9099
  servlet:
    context-path: /server/v1
  # 設置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();
        // 設置處理超時時間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 {
            }
        });
        // 定時處理業(yè)務,處理成功后asyncContext.complete();完成異步請求
        timeoutChecker.scheduleWithFixedDelay(() -> {
            try {
                if (result) {
                    asyncContext.getResponse().getWriter().print(name);
                    asyncContext.complete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 100L, TimeUnit.MILLISECONDS);
    }
    // 模擬業(yè)務處理完成
    @PostMapping("/notify")
    public void notify(Boolean s) {
        result = s;
    }
}

測試結(jié)果

  • 測試指標

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

  • 測試結(jié)果

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

AsyncContext應用場景

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

背景

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

公司由于服務架構調(diào)整,要將該系統(tǒng)改造成基于SpringBoot的Http協(xié)議接口,如果”支付結(jié)果查詢接口“不做機制的變更,就會導致每一次結(jié)果查詢都會阻塞等待隊列中查詢支付結(jié)果的查詢,因為支付是異步的,所以支付結(jié)果查詢會比較耗時,如果機制不改那么如果并發(fā)增大的話會導致服務器的處理請求線程全部被打滿,整個服務對于其他請求,其他業(yè)務都變得不可用了,這個結(jié)果是不可以接受的。

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

基于示例中的demo進行業(yè)務改造

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

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

相關文章

  • 詳解RabbitMq如何做到消息的可靠性投遞

    詳解RabbitMq如何做到消息的可靠性投遞

    這篇文章主要為大家介紹了RabbitMq如何做到消息的可靠性投遞,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 解決idea中servlet報紅問題

    解決idea中servlet報紅問題

    這篇文章主要介紹了解決idea中servlet報紅問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Java Web使用簡單的批處理操作(記事本+Tomcat)

    Java Web使用簡單的批處理操作(記事本+Tomcat)

    這篇文章主要介紹了Java Web使用簡單的批處理操作 ,需要的朋友可以參考下
    2014-10-10
  • Java GUI圖形界面開發(fā)實現(xiàn)小型計算器流程詳解

    Java GUI圖形界面開發(fā)實現(xiàn)小型計算器流程詳解

    本文章向大家介紹Java GUI圖形界面開發(fā)實現(xiàn)小型計算器,主要包括布局管理器使用實例、應用技巧、基本知識點總結(jié)和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • JDK8中String的intern()方法實例詳細解讀

    JDK8中String的intern()方法實例詳細解讀

    String字符串在我們?nèi)粘i_發(fā)中最常用的,當然還有他的兩個兄弟StringBuilder和StringBuilder,接下來通過本文給大家介紹JDK8中String的intern()方法詳細解讀,需要的朋友可以參考下
    2022-09-09
  • Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法

    Eclipse 出現(xiàn)A configuration with this name already exists問題解決方

    這篇文章主要介紹了Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法的相關資料,需要的朋友可以參考下
    2016-11-11
  • Java基礎學習筆記之數(shù)組詳解

    Java基礎學習筆記之數(shù)組詳解

    這篇文章主要介紹了Java基礎學習筆記之數(shù)組,結(jié)合實例形式詳細分析了java的基本概念、定義、迭代、輸出、反轉(zhuǎn)、排序等常用操作技巧,需要的朋友可以參考下
    2019-08-08
  • Java Web請求與響應實例詳解

    Java Web請求與響應實例詳解

    這篇文章主要介紹了Java Web請求與響應實例詳解的相關資料,需要的朋友可以參考下
    2016-05-05
  • Spring高級注解@PropertySource詳細解讀

    Spring高級注解@PropertySource詳細解讀

    這篇文章主要介紹了Spring高級注解@PropertySource詳細解讀,@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過YAML解析器,配合自定義PropertySourceFactory實現(xiàn)解析yaml文件,需要的朋友可以參考下
    2023-11-11
  • Java transient關鍵字與序列化操作實例詳解

    Java transient關鍵字與序列化操作實例詳解

    這篇文章主要介紹了Java transient關鍵字與序列化操作,結(jié)合實例形式詳細分析了java序列化操作相關實現(xiàn)方法與操作注意事項,需要的朋友可以參考下
    2019-09-09

最新評論