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

Java servlet通過事件驅動進行高性能長輪詢詳解

 更新時間:2022年06月16日 09:39:23   作者:hi wei  
這篇文章主要介紹了基于servlet3.0+事件驅動實現(xiàn)高性能長輪詢的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

servlet3.0的異步原理

servlet基礎就不做介紹了,這里就介紹servlet3.0的一個重要的新特性:異步。

servlet3.0原理圖:

  • tomcat接收到客戶端的請求后會將請求AsyncContext交給業(yè)務線程,這樣tomcat工作線程就能釋放出來處理其它請求的連接。
  • 業(yè)務線程池接收到AsyncContext后,就可以處理請求業(yè)務,完成業(yè)務邏輯后,根據(jù)AsyncContext獲取response,返回響應結果。
  • AsyncListener會監(jiān)聽AsyncContext的行為,我們可以根據(jù)具體的行為做出對應的業(yè)務處理。

servlet3.0將tomcat工作線程和業(yè)務線程分隔開來,這樣tomcat工作線程就能處理更多的連接請求。業(yè)務線程主要處理業(yè)務邏輯。在這種模式下,可以更好的分配業(yè)務線程的數(shù)量,也能根據(jù)不同的業(yè)務,設置不同的線程數(shù)量,更加靈活。

注意:tomcat的NIO和servlet3.0的異步?jīng)]有關系。tomcat NIO模式,是對于http連接的處理使用,目的是用更少的線程處理更多的連接。servlet3.0是在tomcat工作線程的處理邏輯上實現(xiàn)異步處理功能。

使用servlet3.0實現(xiàn)長輪詢

什么是長輪詢:

  • 長輪詢是指客戶端會一直向服務端發(fā)起請求,適用與服務端向客戶端推送數(shù)據(jù)使用。長輪詢要滿足以下幾點: 客戶端發(fā)起請求后,當服務端業(yè)務沒有數(shù)據(jù)時,不會立即返回空值,而是hold住連接,等待數(shù)據(jù)生成后立即返回。
  • 請求在服務端有超時時間,不會一直hold住。當超時后,服務端會返回超時信息,客戶端收到返回后會再次發(fā)起請求。
  • 每次請求結束后,客戶端會再次發(fā)起請求。

短輪詢、長輪詢和長連接比較:

  • 短輪詢:客戶端定時向服務器發(fā)送Ajax請求,服務器接到請求后馬上返回響應信息并關閉連接。

優(yōu)點:后端程序編寫比較容易,適于小型應用。。

缺點:請求中有大半是無用,浪費帶寬和服務器資源。

  • 長輪詢:客戶端向服務器發(fā)送Ajax請求,服務器接到請求后hold住連接,直到有新消息才返回響應信息并關閉連接,客戶端處理完響應信息后再向服務器發(fā)送新的請求。

優(yōu)點:在無消息的情況下不會頻繁的請求。

缺點:服務器hold連接會消耗資源。

  • 長連接:客戶端與服務端建立長連接socket

優(yōu)點:可靠性高,實時性高。

缺點:實現(xiàn)復雜,要維護心跳,服務器維持連接消耗資源。

長輪詢實現(xiàn)

原理圖:

  • 請求過來之后,生成事件,加入對應的事件集合。請求設置30s超時時間,并添加監(jiān)聽。tomcat工作線程釋放。
  • 當服務端數(shù)據(jù)準備好之后,觸發(fā)對應事件,從容器獲取訂閱事件進行執(zhí)行。完成后返回response。
  • 請求超時,listener觸發(fā),返回超時信息。

下面看下具體實現(xiàn):

事件定義,這里只是定義一個簡單的事件:

package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
public class HttpEvent {
    /**
     * 可以是業(yè)務數(shù)據(jù)主鍵,這里用請求名稱做個簡單demo
     */
    private String requestName;
    private AsyncContext asyncContext;
    public HttpEvent(String requestName,AsyncContext asyncContext){
        this.requestName = requestName;
        this.asyncContext = asyncContext;
    }
    public String getRequestName() {
        return requestName;
    }
    public AsyncContext getAsyncContext() {
        return asyncContext;
    }
}

事件管理器:

package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
public class EventManager {
    private final static Map<String,HttpEvent> subHttpEvents = new HashMap<>();
    /**
     * 新增事件訂閱
     * @param event
     */
    public static void addHttpEvent(HttpEvent event){
        subHttpEvents.put(event.getRequestName(),event);
    }
    /**
     * 觸發(fā)事件
     * @param requestName
     */
    public static void onEvent(String requestName){
        HttpEvent httpEvent = subHttpEvents.get(requestName);
        if(httpEvent==null){
            return;
        }
        AsyncContext asyncContext = httpEvent.getAsyncContext();
        try {
            PrintWriter writer = asyncContext.getResponse().getWriter();
            writer.print(requestName+" request success!");
            writer.flush();
            asyncContext.complete();
            subHttpEvents.remove(requestName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

異步請求監(jiān)聽器:

package com.hiwe.demo.listener;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;
import java.io.IOException;
import java.io.PrintWriter;
@WebListener
public class AppAsyncListener implements AsyncListener {
    @Override
    public void onComplete(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onComplete");
        // we can do resource cleanup activity here
    }
    @Override
    public void onError(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onError");
        //we can return error response to client
    }
    @Override
    public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onStartAsync");
        //we can log the event here
    }
    /**
     * 超時觸發(fā)
     * @param asyncEvent
     * @throws IOException
     */
    @Override
    public void onTimeout(AsyncEvent asyncEvent) throws IOException {
        AsyncContext asyncContext = asyncEvent.getAsyncContext();
        ServletResponse response = asyncEvent.getAsyncContext().getResponse();
        PrintWriter out = response.getWriter();
        //返回code碼,以便前端識別,并重建請求
        out.write(201+" longPolling timeout");
        out.flush();
        asyncContext.complete();
    }
}

長輪詢接口:

package com.hiwe.demo.controller;
import com.hiwe.demo.listener.AppAsyncListener;
import com.hiwe.demo.event.EventManager;
import com.hiwe.demo.event.HttpEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/app")
public class AsyncController {
    /**
     * 長輪詢接口
     * @param requestName
     * @param request
     * @param response
     */
    @GetMapping("/asyncGet")
    public void getDemo(@RequestParam(value = "requestName") String requestName, HttpServletRequest request, HttpServletResponse response){
        //開啟異步支持
        request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
        AsyncContext asyncContext = request.startAsync();
        //添加監(jiān)聽器
        asyncContext.addListener(new AppAsyncListener());
        //設置超時時間
        asyncContext.setTimeout(30000);
        //添加到事件集合中去
        HttpEvent httpEvent = new HttpEvent(requestName, asyncContext);
        EventManager.addHttpEvent(httpEvent);
    }
    /**
     * 觸發(fā)事件使用
     * @param requestName
     */
    @GetMapping("/trigger")
    public void triggerDemo(@RequestParam(value = "requestName") String requestName){
        EventManager.onEvent(requestName);
    }
}

以上一個簡單的長輪詢就實現(xiàn)了,我們可以進行一下測試:

啟動應用后訪問:http://localhost:8080/app/asyncGet?requestName=123

服務端因為數(shù)據(jù)未準備就緒,所以會hold住請求。當?shù)却?0s后會返回超時信息:

我們在30s內(nèi)觸發(fā)event:http://localhost:8080/app/trigger?requestName=123

返回:

以上整個長輪詢實現(xiàn)完成了,如果有錯誤,歡迎指正!

到此這篇關于Java servlet通過事件驅動進行高性能長輪詢詳解的文章就介紹到這了,更多相關Java 高性能長輪詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解mybatis通過mapper接口加載映射文件

    詳解mybatis通過mapper接口加載映射文件

    本篇文章主要介紹了mybatis通過mapper接口加載映射文件 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Java中final與繼承操作實例分析

    Java中final與繼承操作實例分析

    這篇文章主要介紹了Java中final與繼承操作,結合實例形式分析了Java中使用final阻止繼承的相關原理與操作注意事項,需要的朋友可以參考下
    2019-09-09
  • Spring Boot項目中定制攔截器的方法詳解

    Spring Boot項目中定制攔截器的方法詳解

    這篇文章主要介紹了Spring Boot項目中定制攔截器的方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • Java時間復雜度、空間復雜度的深入詳解

    Java時間復雜度、空間復雜度的深入詳解

    對于一個算法,其時間復雜度和空間復雜度往往是相互影響的,當追求一個較好的時間復雜度時,可能會使空間復雜度的性能變差,即可能導致占用較多的存儲空間,這篇文章主要給大家介紹了關于Java時間復雜度、空間復雜度的相關資料,需要的朋友可以參考下
    2021-11-11
  • Java中用爬蟲進行解析的實例方法

    Java中用爬蟲進行解析的實例方法

    在本篇文章里小編給大家整理的是一篇關于Java中用爬蟲進行解析的實例方法,有需要的朋友們可以學習參考下。
    2020-12-12
  • 使用java實現(xiàn)LIS算法,出操隊形的問題

    使用java實現(xiàn)LIS算法,出操隊形的問題

    下面小編就為大家?guī)硪黄褂胘ava實現(xiàn)LIS算法,出操隊形的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • springboot自定義yml配置文件及其外部部署過程

    springboot自定義yml配置文件及其外部部署過程

    這篇文章主要介紹了springboot自定義yml配置文件及其外部部署過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 解決	Spring RestTemplate post傳遞參數(shù)時報錯問題

    解決 Spring RestTemplate post傳遞參數(shù)時報錯問題

    本文詳解說明了RestTemplate post傳遞參數(shù)時報錯的問題及其原由,需要的朋友可以參考下
    2020-02-02
  • Java設計圖形與多媒體處理

    Java設計圖形與多媒體處理

    本文主要介紹了Java的圖形設計以及多媒體處理,源碼也做了詳細的注釋,對于初學者應該不難。詳細請看下文
    2015-09-09
  • Spring Boot 中的 SockJS原理及使用方法

    Spring Boot 中的 SockJS原理及使用方法

    SockJS 的主要作用是提供一種 WebSocket 的兼容性解決方案,使得不支持 WebSocket 的瀏覽器也可以使用 WebSocket,本文介紹了Spring Boot中的SockJS,包括SockJS的原理,使用方法和示例代碼,感興趣的朋友跟隨小編一起看看吧
    2023-07-07

最新評論