為什麼ChatGPT採用SSE協議而不是Websocket?
來源:程式新視界
在探索ChatGPT的使用過程中,我們發現GPT採用了流式資料返回的方式。理論上,這種情況可以透過全雙工通訊協議實現持久化連線,或者依賴於基於EventStream的事件流。然而,ChatGPT選擇了後者,也就是本文即將深入探討的SSE(Server-Sent Events)技術。
要理解這個選擇,我們需要關注ChatGPT的使用場景。作為一個基於深度學習的大型語言模型,ChatGPT需要處理大量的自然語言資料,這無疑需要大量的計算資源和時間。相較於普通的讀取資料庫操作,其響應速度自然會慢許多。
對於這種可能需要長時間等待響應的對話場景,ChatGPT採用了一種巧妙的策略:它會將已經計算出的資料“推送”給使用者,並利用SSE技術在計算過程中持續返回資料。這樣做可以避免使用者因等待時間過長而選擇關閉頁面。
什麼是 SSE?
SSE(Server-Sent Events)是一種Web技術,它允許伺服器實時向客戶端推送資料。相比於傳統的輪詢和長輪詢機制,SSE提供了一種更高效且實時的資料推送方式。這種技術主要應用於構建實時應用,例如實時訊息推送、股票行情更新等。
SSE是HTML5規範中的一個通訊相關API,它主要包含兩個部分:服務端與瀏覽器端的通訊協議(基於HTTP協議),以及瀏覽器端JavaScript可使用的EventSource物件。
SSE執行在HTTP協議之上,它允許伺服器以事件流(Event Stream)的形式將資料傳送給客戶端。客戶端透過建立持久化的HTTP連線,並監聽這個事件流,從而可以實時接收到伺服器推送的資料。
SSE具有以下幾個主要特點:
簡單易用:SSE使用基於文字的資料格式,如純文字、JSON等,這使得資料傳送和解析都相對簡單直接。 單向通訊:SSE僅支援從伺服器到客戶端的單向通訊。這意味著伺服器可以主動推送資料給客戶端,但客戶端只能被動接收資料。 實時性:由於SSE能夠建立持久化連線,伺服器因此可以實時地將資料推送給客戶端,無需客戶端頻繁地發起請求。這大大提高了資料傳輸的效率和實時性。
SSE與WebSocket的比較
WebSocket是一種Web技術,用於實現實時雙向通訊,它與SSE(Server-Sent Events)在某些方面存在差異。以下是對兩者的比較:
資料推送方向:SSE主要支援從伺服器到客戶端的單向通訊,這意味著伺服器可以主動地向客戶端推送資料。而WebSocket則支援雙向通訊,允許伺服器和客戶端之間進行實時的資料交換。 連線建立:SSE利用基於HTTP的長連線,透過常規的HTTP請求和響應來建立連線,進而實現資料的實時推送。相反,WebSocket採用自定義的協議,透過建立WebSocket連線來實現雙向通訊。 相容性:由於SSE基於HTTP協議,因此它可以在大多數現代瀏覽器中使用,並且無需進行額外的協議升級。雖然WebSocket在絕大多數現代瀏覽器中也得到了支援,但在某些特定的網路環境下可能會遇到問題。 適用場景:SSE適合於需要伺服器向客戶端實時推送資料的場景,例如股票價格更新、新聞實時推送等。而WebSocket則適合於需要實時雙向通訊的場景,如聊天應用、多人線上協作編輯等。
選擇使用SSE還是WebSocket主要取決於具體的業務需求和場景。如果你只需要實現從伺服器向客戶端的單向資料推送,並且希望保持操作簡便且相容性好,那麼SSE是一個理想的選擇。然而,如果你需要實現雙向通訊,或者需要更高階的功能和控制,那麼WebSocket可能會更適合你的需求。
SSE的實現原理
以下是SSE(Server-Sent Events)的實現原理:
連線建立:通常情況下,客戶端(如瀏覽器)透過傳送HTTP GET請求到伺服器來請求建立一個SSE連線。 伺服器響應:一旦伺服器接收到請求,它將返回一個HTTP響應,該響應的狀態碼為200,內容型別(Content-Type)設定為"text/event-stream"。 資料推送:伺服器可以透過已經建立的連線向客戶端推送資料。每次推送的資料被稱作一個事件(Event)。每個事件由一個或多個以"\n\n"分隔的資料塊組成。每個資料塊都是一行文字,可能包含一個以":"開頭的註釋行、以"data:"開頭的資料行,或者以"id:"和"event:"開頭的行來指定事件ID和事件型別。 客戶端處理:當客戶端接收到伺服器推送的事件後,它會觸發相應的JavaScript事件處理器來處理這些事件。 重連:如果連線斷開,客戶端會自動嘗試重新連線。如果伺服器在事件中指定了ID,那麼在重新連線時,客戶端會傳送一個"Last-Event-ID"的HTTP頭部資訊到伺服器,告訴伺服器客戶端接收到的最後一個事件的ID。根據這個資訊,伺服器可以決定從哪個事件開始重新傳送資料。
總結起來,SSE使用了基於文字和HTTP協議的簡單機制,使得伺服器能夠實時地將資料推送到客戶端,而無需客戶端頻繁地發起新的請求。
使用SSE的注意事項
以下是在使用SSE(Server-Sent Events)技術進行實時資料推送時需要注意的幾個關鍵點:
非同步處理:由於SSE基於長連線的機制,因此資料推送過程可能會持續較長時間。為了防止伺服器執行緒被阻塞,建議採用非同步方式處理SSE請求。例如,可以在控制器方法中使用@Async註解或利用CompletableFuture等非同步程式設計方式。 超時處理:SSE連線可能會因網路中斷、客戶端關閉等原因而超時。為了避免無效連線佔據伺服器資源,建議設定超時時間並處理超時情況。例如,可以利用SseEmitter物件的setTimeout()方法設定超時時間,並透過onTimeout()方法處理超時邏輯。 異常處理:在實際應用中,可能會遇到網路異常、資料推送失敗等問題。這種情況下,可以使用SseEmitter物件的completeWithError()方法將異常資訊傳送給客戶端,並在客戶端透過eventSource.onerror事件進行處理。 記憶體管理:在使用SseEmitter時,需要特別注意記憶體管理問題,尤其是在大量併發連線的場景下。當客戶端斷開連線後,務必及時釋放SseEmitter物件,以避免資源洩漏和記憶體溢位。 併發效能:SSE的併發連線數可能對伺服器效能產生影響。如果需要處理大量併發連線,可以考慮使用執行緒池或其他非同步處理方式,以最大化伺服器資源利用。 客戶端相容性:雖然大多數現代瀏覽器都支援SSE,但一些舊版本的瀏覽器可能不支援。因此,在使用SSE時,需要確保目標客戶端對其有良好的支援,或者提供備選的實時資料推送機制。
以上這些注意事項可以根據具體應用需求進行調整和最佳化。在實際應用中,確保伺服器的穩定性、安全性和效能是非常重要的。同時,在處理SSE連線時,可以考慮適當的限流和安全控制措施,以防止濫用和惡意連線的出現。總的來說,使用SSE技術時需要全面考慮各個方面的因素,才能實現高效、穩定、安全的實時資料推送服務。
SpringBoot整合SSE案例
假設正在開發一個實時股票價格監控應用,需要將股票價格實時推送給客戶端。以下為Spring Boot中整合SSE技術實現的場景示例程式碼。
首先,定義一個控制器來處理SSE請求和傳送實時股票價格:
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.Random;
@RestController
public class StockController {
@GetMapping(value = "/stock-price", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamStockPrice() {
SseEmitter emitter = new SseEmitter();
// 模擬生成實時股票價格並推送給客戶端
Random random = new Random();
new Thread(() -> {
try {
while (true) {
// 生成隨機的股票價格
double price = 100 + random.nextDouble() * 10;
// 構造股票價格的訊息
String message = String.format("%.2f", price);
// 傳送訊息給客戶端
emitter.send(SseEmitter.event().data(message));
// 休眠1秒鐘
Thread.sleep(1000);
}
} catch (Exception e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
}
在上述程式碼中,定義了一個streamStockPrice()
方法,該方法使用@GetMapping
註解將/stock-price
路徑對映到該方法上,並指定produces = MediaType.TEXT_EVENT_STREAM_VALUE
以表明該方法將產生SSE事件流。
在方法內部建立了一個SseEmitter
物件作為事件發射器,並在一個單獨的執行緒中不斷生成隨機的股票價格,並將價格轉換為字串形式傳送給客戶端。
透過emitter.send()
方法傳送的資料會被封裝為SSE事件流的形式,客戶端可以透過監聽該事件流來實時接收股票價格。
在前端頁面中,建立一個簡單的HTML頁面來展示實時股票價格:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>實時股票價格監控</title>
</head>
<body>
<h1>實時股票價格</h1>
<div id="stock-price"></div>
<script>
const eventSource = new EventSource('/stock-price');
eventSource.onmessage = function (event) {
document.getElementById('stock-price').innerHTML = event.data;
};
</script>
</body>
</html>
上述程式碼中,透過new EventSource('/stock-price')
建立了一個EventSource
物件,它與/stock-price
路徑建立SSE連線。然後,透過eventSource.onmessage
定義了接收訊息的回撥函式,在收到新訊息時更新頁面上的股票價格。
透過以上程式碼,可以在瀏覽器中開啟該HTML頁面,它會建立與伺服器的SSE連線,並實時接收並展示股票價格。這只是使用SSE實現實時資料推送的一個簡單示例。在實踐中,可以根據具體的業務需求和場景,進行更復雜和豐富的實現。
小結
SSE(Server-Sent Events)是一種基於HTTP協議的輕量級實時通訊技術,具備服務端推送、斷線重連和簡單輕量等優點。然而,它也存在一些限制,例如無法進行雙向通訊、連線數受限以及僅支援GET請求等。
在Web應用程式中,SSE可以實現各種即時資料推送功能,如股票線上資料更新、日誌推送、實時顯示聊天室人數等。
然而,需要注意的是,並非所有的實時推送場景都適合使用SSE。在需要處理高併發、高吞吐量和低延遲的場景下,WebSocket可能是更好的選擇。而對於那些需要輕量級推送解決方案的場景,SSE可能會更加適合。
因此,在選擇實時更新方案時,我們需要根據具體的需求和應用場景來做出決策。只有這樣,我們才能確保選擇的技術能夠最大程度地滿足我們的需求。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70027828/viewspace-3004611/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在Linux中,我們都知道,dns採用了tcp協議,又採用了udp協議,什麼時候採用tcp協議?什麼 時候採用udp協議?為什麼要這麼設計?LinuxDNSTCP協議UDP
- 什麼是WebSocket協議Web協議
- OceanBase的一致性協議為什麼選擇 Paxos 而不是 Raft?協議Raft
- 居中為什麼用transform,而不是margin top/leftORM
- 為什麼ChatGPT不是誕生在中國?ChatGPT
- 什麼是HTTPS協議?為什麼要用HTTPS協議?HTTP協議
- websocket和http有什麼不同?以及websocket協議如何實現?WebHTTP協議
- WebSocket協議Web協議
- 為什麼DNS使用UDP而不是TCP詳解!DNSUDPTCP
- 為什麼你應當選擇 PostgreSQL 而不是 Oracle?SQLOracle
- 網際網路公司為什麼普遍996而不是666?996
- 為什麼VSCode是程式碼編輯器而不是IDE?VSCodeIDE
- 分散式鎖為什麼要選擇Zookeeper而不是Redis?分散式Redis
- SPC控制圖為什麼是±3σ,而不是±2σ或±4σ?
- 為什麼爬蟲語言選擇Python而不是Java?爬蟲PythonJava
- 深入淺出Websocket(一)Websocket協議Web協議
- WebSocket協議 8 問Web協議
- 關於WebSocket協議Web協議
- WebSocket 協議詳解Web協議
- [譯] 為什麼我更喜歡物件而不是switch語句物件
- gRPC為什麼使用截止時間而不是超時時間?RPC
- WebSocket原理與實踐(二)---WebSocket協議Web協議
- 為什麼 TCP 協議有效能問題TCP協議
- WebSocket的Frame協議解析Web協議
- WebSocket 協議 1~4 節Web協議
- WebSocket 協議 5~10 節Web協議
- 【譯】WebSocket協議——摘要(Abstract)Web協議
- Locust 壓測websocket協議Web協議
- 為啥儲存 IP 用 bigint 而不是 char
- 美團一面:Spring Cloud 遠端呼叫為啥要採用 HTTP,而不是 RPC?SpringCloudHTTPRPC
- 從崩潰的選課系統,論為什麼更安全的 HTTPS 協議沒有被全面採用HTTP協議
- 淺談WebSocket協議、WS協議和WSS協議原理及關係Web協議
- 為什麼DRAM採用地址複用技術?為什麼SRAM不採用地址複用技術?
- 【譯】 WebSocket 協議第十二章——使用其他規範中的WebSocket協議Web協議
- 為什麼我更喜歡定期合併提交而不是壓縮提交
- 為什麼爬蟲語言大多都會選擇Python而不是Java?爬蟲PythonJava
- 為什麼執行緒安全的List推薦使用CopyOnWriteArrayList,而不是Vector執行緒
- 什麼是協議?| 網路協議定義協議