客戶端接收消息的幾種方式


前言

系統的業務中,網頁需要彈窗"報警信息"。前端獲取數據的方式通過輪詢調后端接口。也考慮過WebSocket 的方式,但好像兼容性不太好。現在發現還有其他更優的方式,在此記錄一下。

網頁端收服務端的消息的方式

一、輪詢拉取

客戶端間隔的發送ajax請求服務器的數據。

  • 優點:實現簡單
  • 缺點:
    • 實時性比較差,最大時差就是前端的間隔
    • 效率低:如果長時間沒有消息,客戶端還是在輪詢請求。浪費服務端的資源
二、建立長連接
  • 如果要兼顧實時性和效率,長連接是最佳之選,PC端聊天軟件基本都是使用長連接。網頁端常見的實現長連接的方式有兩種:WebSocket和FlashSocket
  • 缺點:兼容性差,有些瀏覽器不支持
三、Http長輪詢 (通用方式)

通過HTTP短連接拼裝長連接,具體是通過“夯住”“只收推送通知”的“通知連接”來實現的,能夠做到消息的實時性到達。

客戶端向服務器發送Ajax請求,服務器接到請求后hold住連接,直到有新消息才返回響應信息並關閉連接,客戶端處理完響應信息后再向服務器發送新的請求

在瀏覽器和服務端建立了一條"通知連接"的特點:

  • 這是一條browser發往web-server的HTTP連接
  • 這條連接只用來收取推送通知
  • 不像普通的“請求-響應”式HTTP請求,這個HTTP會被服務端夯住,直到有推送通知到達,或者超過約定的時間

對於HTTP請求,為了提高效率,一般來說browser和web-server都會有一些設置,如果一條HTTP請求長時間沒有數據(例如,150秒),會被斷開。“通知連接”為了不被browser和web-server粗暴斷開,一般會設置一個約定閾值(例如,小於150秒),由系統返回一個空消息,以便“優雅返回”。

瀏覽器發起通知連接時,如果服務端的隊列里面有消息,則服務端立刻把消息返回。如果這條連接達到了"約定閾值"要斷開時,服務端返回空消息維持連接。當服務端返回消息(空的或者真實消息)的同時,瀏覽器會瞬間再發起連接。在消息過去和瀏覽器返回的時間差時有消息時,服務端將新的消息放入隊列(發生概率很小)

  • 缺點:服務器hold連接會消耗資源
實現Http長輪詢

使用 DeferredResult 異步請求處理

@GetMapping("/async-deferredresult")
public DeferredResult<ResponseEntity<?>> handleReqDefResult(Model model) {
    LOG.info("Received async-deferredresult request");
    DeferredResult<ResponseEntity<?>> output = new DeferredResult<>();
     
    ForkJoinPool.commonPool().submit(() -> {
        LOG.info("Processing in separate thread");
        try {
            Thread.sleep(6000); // 模擬延遲六秒返回
        } catch (InterruptedException e) {
        }
        output.setResult(ResponseEntity.ok("ok"));
    });
     
    LOG.info("servlet thread freed");
    return output;
}


// 設置超時,即在后端一致沒有數據的情況下,多長時間斷開連接。使用的是onTimeout()方法。
deferredResult.onTimeout(() -> 
  deferredResult.setErrorResult(
    ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT)
      .body("Request timeout occurred.")));
      
 
 // 如果后端出現了錯誤,可以設置onError()方法修改返回狀態碼:     
deferredResult.onError((Throwable t) -> {
    deferredResult.setErrorResult(
      ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
        .body("An error occurred."));
})      
      

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM