WebSockets與SSE大對(duì)決:誰(shuí)才是實(shí)時(shí)通信的王者?
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
在今天的博文中,我想深入探討服務(wù)器發(fā)送事件(簡(jiǎn)稱SSE)和WebSockets。這兩種方法都是經(jīng)過(guò)實(shí)戰(zhàn)考驗(yàn)的數(shù)據(jù)交換方式。 我將首先簡(jiǎn)要介紹這兩種工具的特性——它們是什么以及提供什么功能。然后,我會(huì)根據(jù)八個(gè)類別對(duì)它們進(jìn)行比較,我認(rèn)為這些類別對(duì)于現(xiàn)代系統(tǒng)來(lái)說(shuō)最為關(guān)鍵。 與我之前比較REST和qRPC不同,我不會(huì)在每個(gè)類別中宣布任何勝者或授予分?jǐn)?shù)。相反,在“總結(jié)”段落中,你會(huì)找到一個(gè)類似TL;DR的表格。該表格包含在上述領(lǐng)域中兩種技術(shù)的關(guān)鍵差異。 與REST不同,SSE和WebSockets都更專注于特定的用例。在這種情況下,這兩個(gè)概念的主要關(guān)注點(diǎn)是提供一個(gè)“實(shí)時(shí)”通信媒介。由于它們的特定關(guān)注點(diǎn),它們不如REST流行,REST是一種更通用的、一刀切的工具。 不過(guò),SSE和WebSockets都提供了一組有趣的可能性,為經(jīng)典的REST方法解決復(fù)雜問(wèn)題提供了輕微的更新。在我看來(lái),最好了解它們并在我們的工具箱中為它們找到一席之地,因?yàn)橛幸惶焖鼈兛赡軙?huì)派上用場(chǎng)。當(dāng)你需要“實(shí)時(shí)”更新或你的應(yīng)用程序需要更推送導(dǎo)向的方法時(shí),它們可以為你提供一個(gè)更簡(jiǎn)單的解決方案。 簡(jiǎn)而言之,它是一種通信協(xié)議,通過(guò)使用一個(gè)持久的TCP連接在服務(wù)器和客戶端之間提供雙向通信。由于這一特性,我們不必不斷從服務(wù)器拉取新數(shù)據(jù)。相反,數(shù)據(jù)在相關(guān)方之間“實(shí)時(shí)”交換。每個(gè)消息要么是二進(jìn)制數(shù)據(jù),要么是Unicode文本。 該協(xié)議于2011年由IETF以RFC 6455的形式標(biāo)準(zhǔn)化。WebSocket協(xié)議與HTTP不同,但兩者都位于OSI模型的第七層,并依賴第四層的TCP。 該協(xié)議有一套獨(dú)特的前綴,類似于HTTP的http和https前綴: 此外,從安全站點(diǎn)(https)不應(yīng)打開非安全的WebSocket連接(ws)。類似地,從非安全站點(diǎn)(http)不應(yīng)打開安全的WebSocket連接(wss)。 另一方面,WebSocket按設(shè)計(jì)在HTTP端口443和80上工作,并支持HTTP概念,如代理和中間件。此外,WebSocket握手使用HTTP升級(jí)頭來(lái)將協(xié)議從HTTP升級(jí)到WebSocket。 WebSocket作為一個(gè)協(xié)議的最大缺點(diǎn)是安全性。WebSocket不受同源策略的限制,這可能使類似CSRF的攻擊更容易。 SSE是一種允許網(wǎng)絡(luò)服務(wù)器向網(wǎng)頁(yè)發(fā)送更新的技術(shù)。它是HTML 5規(guī)范的一部分,與WebSockets類似,使用一個(gè)持久的HTTP連接來(lái)“實(shí)時(shí)”發(fā)送數(shù)據(jù)。在概念層面上,它是一種相當(dāng)古老的技術(shù),其理論背景可以追溯到2004年。2006年,Opera團(tuán)隊(duì)首次嘗試實(shí)現(xiàn)SSE。 SSE得到了大多數(shù)現(xiàn)代瀏覽器的支持——Microsoft Edge于2020年1月添加了SSE支持。它還可以充分利用HTTP/2,這實(shí)際上消除了SSE的一個(gè)最大問(wèn)題,即實(shí)際上消除了HTTP/1.1所施加的連接限制。 根據(jù)規(guī)范,服務(wù)器發(fā)送事件有兩個(gè)基本構(gòu)建塊: 根據(jù)規(guī)范,事件可以攜帶任意文本數(shù)據(jù),一個(gè)可選的ID,并由換行符分隔。它們甚至有其獨(dú)特的MIME類型:text/event-stream。 此外,SSE提供了兩個(gè)非常有趣的特性: 可能是這兩種技術(shù)之間最大的區(qū)別在于它們的通信方式。 我會(huì)在接下來(lái)的段落中描述所有這些領(lǐng)域以及更多內(nèi)容。此外,在所有情況下使用WebSocket可能是一個(gè)重大過(guò)度,基于SSE的解決方案可能更簡(jiǎn)單易行。 這里出現(xiàn)了這兩種技術(shù)之間的另一個(gè)重大區(qū)別。 在SSE的情況下,使用HTTP/2解決了SSE的一個(gè)主要問(wèn)題——最大并行連接限制。HTTP/1.1根據(jù)其規(guī)范限制并行連接的數(shù)量。 這種行為可能導(dǎo)致一個(gè)稱為頭部阻塞的問(wèn)題。HTTP/2通過(guò)引入多路復(fù)用解決了這個(gè)問(wèn)題,從而在應(yīng)用層解決了頭部阻塞問(wèn)題。然而,TCP級(jí)別的頭部阻塞仍然可能發(fā)生。 至于WebSocket協(xié)議,我在上面幾行中已經(jīng)詳細(xì)提及。在這里,我只會(huì)重申最重要的幾點(diǎn)。該協(xié)議與經(jīng)典的HTTP有些不同,盡管使用HTTP升級(jí)頭來(lái)初始化WebSocket連接并有效地更改通信協(xié)議。 盡管如此,它還以TCP協(xié)議為基礎(chǔ),并且與HTTP完全兼容。WebSocket協(xié)議最大的缺點(diǎn)是其安全性。 一般來(lái)說(shuō),設(shè)置基于SSE的集成比其WebSocket對(duì)應(yīng)物更簡(jiǎn)單。其背后最重要的原因是特定技術(shù)所利用的通信性質(zhì)。 SSE的單向通信方式及其推送模型在概念層面上使其更簡(jiǎn)單。結(jié)合自動(dòng)重連和流連續(xù)性支持,SSE開箱即用,減少了我們需要處理的事情的數(shù)量。 在WebSocket的情況下,事情變得有點(diǎn)復(fù)雜。首先,我們需要處理從HTTP到WebSocket協(xié)議的連接升級(jí)。盡管這是最簡(jiǎn)單的事情之一,但仍然是我們需要記住的另一件事。 第二個(gè)問(wèn)題是WebSocket的雙向性質(zhì)。我們必須管理特定連接的狀態(tài),并處理在處理消息時(shí)發(fā)生的所有可能的異常。例如,如果服務(wù)器端處理其中一個(gè)消息時(shí)拋出異常,我們?cè)撛趺崔k? 接下來(lái)是處理重連的問(wèn)題,這在WebSocket的情況下需要我們自己處理。 還存在影響這兩種技術(shù)的問(wèn)題——長(zhǎng)連接。 這兩種技術(shù)都需要維護(hù)長(zhǎng)連接以發(fā)送持續(xù)的事件流。 在大規(guī)模管理這些連接可能是一個(gè)挑戰(zhàn),因?yàn)槲覀兛赡芎芸旌谋M資源。此外,它們可能需要特殊配置,如延長(zhǎng)超時(shí)時(shí)間,并且更容易受到任何網(wǎng)絡(luò)連接問(wèn)題的影響。 對(duì)于SSE來(lái)說(shuō),安全性沒(méi)有什么特別之處,因?yàn)樗褂肏TTP協(xié)議作為傳輸介質(zhì)。所有標(biāo)準(zhǔn)的HTTP優(yōu)點(diǎn)和缺點(diǎn)都適用于SSE,非常簡(jiǎn)單。 另一方面,安全性是WebSocket協(xié)議作為一個(gè)整體最大的缺點(diǎn)之一。首先,沒(méi)有同源策略,因此我們可以通過(guò)WebSocket連接到任何地方,沒(méi)有任何限制。 甚至有一種專門針對(duì)這種漏洞的攻擊類型,即跨源WebSocket劫持。如果你想要深入了解更多關(guān)于同源策略和WebSocket的內(nèi)容,這里有一篇文章可能會(huì)引起你的興趣。除此之外,WebSocket協(xié)議本身沒(méi)有特定的安全漏洞。 我會(huì)說(shuō),在這兩種情況下,所有標(biāo)準(zhǔn)和最佳安全實(shí)踐都適用,因此在實(shí)現(xiàn)解決方案時(shí)要小心謹(jǐn)慎。 我會(huì)說(shuō),在性能方面,這兩種技術(shù)可以說(shuō)是不相上下。這兩種技術(shù)本身都沒(méi)有理論性能限制。 然而,我會(huì)說(shuō)SSE在每秒發(fā)送的消息數(shù)量方面可能更快,因?yàn)樗裱环N類似“發(fā)送后即忘”的原則。WebSocket還需要處理來(lái)自客戶端的響應(yīng)。 唯一可能影響兩者性能的因素是我們應(yīng)用程序中使用的底層客戶端及其實(shí)現(xiàn)。檢查、閱讀文檔、運(yùn)行自定義壓力測(cè)試,你可能會(huì)對(duì)所使用的工具或整個(gè)系統(tǒng)獲得非常有趣的見解。 消息結(jié)構(gòu)可能是協(xié)議之間另一個(gè)最重要的區(qū)別。 正如我在上面提到的,SSE是一種純文本協(xié)議。我們可以發(fā)送不同格式和內(nèi)容的消息,但最終所有內(nèi)容都以UTF-8編碼的文本形式結(jié)束。不允許復(fù)雜的格式或二進(jìn)制數(shù)據(jù)。 另一方面,WebSocket可以處理文本和二進(jìn)制消息。這使我們能夠發(fā)送圖像、音頻或只是普通文件。只是要記住,處理文件可能會(huì)有顯著的開銷。 在這方面,這兩種技術(shù)處于非常相似的階段。無(wú)論是SSE還是WebSockets,都缺少用于自動(dòng)化測(cè)試的專用工具。然而,你可以相對(duì)容易地使用Postman和集合來(lái)實(shí)現(xiàn)類似功能。 Postman支持SSE和WebSockets。通過(guò)使用Postman集合的一些魔法,你可以準(zhǔn)備一組測(cè)試來(lái)驗(yàn)證端點(diǎn)的正確性。 對(duì)于性能測(cè)試,你可以選擇JMeter或Gatling。據(jù)我所知,這兩個(gè)工具是整體性能測(cè)試中最成熟的工具。當(dāng)然,它們也支持SSE(JMeter,Gatling)和WebSockets(JMeter,Gatling)。 還有其他工具如sse-perf(僅限SSE),Testable或k6(僅限WebSockets)。 在所有這些工具中,我個(gè)人會(huì)推薦Gatling或k6。兩者似乎都有最好的用戶體驗(yàn),并且最接近生產(chǎn)環(huán)境。 在某種程度上,沒(méi)有專門用于為SSE或WebSockets生成文檔的工具。另一方面,有一個(gè)名為AsyncAPI的工具可以以這種方式使用,適用于這兩個(gè)概念。 不幸的是,OpenAPI似乎不支持SSE或WebSockets。 如我所承諾的,總結(jié)將快速而簡(jiǎn)單——請(qǐng)參閱下方表格。 我認(rèn)為上述表格是對(duì)主題和整篇文章的一個(gè)相當(dāng)簡(jiǎn)潔的總結(jié)。 最重要的區(qū)別是通信方向,因?yàn)樗鼪Q定了特定技術(shù)的可能用例。這將對(duì)選擇一個(gè)而不是另一個(gè)產(chǎn)生最大的影響。 消息結(jié)構(gòu)在選擇特定通信方式時(shí)也可能是一個(gè)非常重要的類別。僅允許純文本消息對(duì)于服務(wù)器發(fā)送事件來(lái)說(shuō)是一個(gè)非常顯著的缺點(diǎn)。 閱讀原文:原文鏈接 該文章在 2025/5/29 10:59:07 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |