WebSockets กับเหตุการณ์ที่เซิร์ฟเวอร์ส่ง / EventSource


838

ทั้งWebSocketsและServer-Sent Eventsสามารถส่งข้อมูลไปยังเบราว์เซอร์ได้ สำหรับฉันพวกเขาดูเหมือนจะเป็นเทคโนโลยีการแข่งขัน ความแตกต่างระหว่างพวกเขาคืออะไร? เมื่อใดที่คุณจะเลือกหนึ่งรายการอื่น ๆ


2
ไม่แน่ใจว่าคุณเห็นพวกเขาแข่งขันอย่างไร หนึ่งคือแบบซิงโครนัสและสามารถ / จะใช้สำหรับ xfer ข้อมูลแบบเรียลไทม์ใกล้ ๆ ในขณะที่อีกแบบนั้นแบบอะซิงโครนัสและจะให้บริการที่แตกต่างกันโดยสิ้นเชิง (ส่งข้อความคล้ายขนมปังปิ้ง
Brian Driscoll

54
WebSockets เป็นสองทางสามารถส่งข้อมูลไปยังเซิร์ฟเวอร์
Andre Backlund

13
สิ่งหนึ่งที่ผมชอบเกี่ยวกับ SSE คือว่ามันเป็นเรื่องง่ายที่จะแก้ไขปัญหา ... เพียงแค่เปิดการร้องขอไปยังเซิร์ฟเวอร์ SSE curlของคุณโดยใช้ เนื่องจากเป็นเพียงรูปแบบข้อความบน HTTP จึงง่ายที่จะดูว่าเกิดอะไรขึ้น
Sam

7
@BrianDriscoll - asynchronous / synchronous - อันไหน? เท่าที่ฉันสามารถเข้าใจทั้งเปิดใช้งานการถ่ายโอนแบบอะซิงโครนัส?
Dave Everitt

5
SSE ไม่ทำงานบน IE websockets ใช้งานได้
Tyler Gillies

คำตอบ:


978

Websockets และ SSE (เหตุการณ์ที่ส่งเซิร์ฟเวอร์) มีความสามารถในการส่งข้อมูลไปยังเบราว์เซอร์อย่างไรก็ตามพวกเขาไม่ใช่เทคโนโลยีที่แข่งขันกัน

การเชื่อมต่อ Websockets สามารถส่งข้อมูลไปยังเบราว์เซอร์และรับข้อมูลจากเบราว์เซอร์ ตัวอย่างที่ดีของแอพพลิเคชั่นที่สามารถใช้ websockets คือแอปพลิเคชั่นแชท

การเชื่อมต่อ SSE สามารถส่งข้อมูลไปยังเบราว์เซอร์ได้เท่านั้น ราคาหุ้นออนไลน์หรือ twitters ที่อัปเดตไทม์ไลน์หรือฟีดเป็นตัวอย่างที่ดีของแอปพลิเคชันที่อาจได้รับประโยชน์จาก SSE

ในทางปฏิบัติเนื่องจากทุกสิ่งที่สามารถทำได้ด้วย SSE นั้นสามารถทำได้ด้วย Websockets Websockets ได้รับความสนใจและชื่นชอบเป็นอย่างมากและเบราว์เซอร์จำนวนมากสนับสนุน Websockets มากกว่า SSE

อย่างไรก็ตามมันสามารถ overkill สำหรับแอปพลิเคชันบางประเภทและแบ็กเอนด์อาจจะใช้งานได้ง่ายขึ้นด้วยโปรโตคอลเช่น SSE

นอกจากนี้ SSE ยังสามารถโพลีไฟล์ลงในเบราว์เซอร์รุ่นเก่าที่ไม่รองรับโดยใช้ JavaScript เพียงอย่างเดียว การใช้งานบางส่วนของ polyfills SSE สามารถพบได้บนหน้า Modernizr GitHub

gotchas:

  • SSE ได้รับความทุกข์ทรมานจากการ จำกัด จำนวนการเชื่อมต่อแบบเปิดสูงสุดซึ่งอาจเจ็บปวดเป็นพิเศษเมื่อเปิดแท็บต่าง ๆ เนื่องจากขีด จำกัดต่อเบราว์เซอร์และตั้งค่าเป็นจำนวนต่ำมาก (6) ปัญหาที่ได้รับการระบุว่าเป็น "จะไม่แก้ไข" ในChromeและFirefox ขีด จำกัด นี้เป็นต่อเบราว์เซอร์ + โดเมนดังนั้นหมายความว่าคุณสามารถเปิดการเชื่อมต่อ SSE ได้ 6 ครั้งในแท็บทั้งหมดไปยังwww.example1.comและอีก 6 การเชื่อมต่อ SSE ไปยังwww.example2.com(ขอบคุณ Phate)
  • เฉพาะ WS เท่านั้นที่สามารถส่งได้ทั้งข้อมูลไบนารีและ UTF-8 SSE นั้น จำกัด ที่ UTF-8 (ขอบคุณ Chado Nihi)
  • ไฟร์วอลล์องค์กรบางแห่งที่มีการตรวจสอบแพ็คเก็ตมีปัญหาในการจัดการกับ WebSockets (ไฟร์วอลล์ Sophos XG, WatchGuard, McAfee Web Gateway)

HTML5Rocksมีข้อมูลที่ดีเกี่ยวกับ SSE จากหน้านั้น:

เหตุการณ์ที่เซิร์ฟเวอร์ส่งเทียบกับ WebSockets

เหตุใดคุณจึงเลือกเหตุการณ์ที่เซิร์ฟเวอร์ส่งผ่าน WebSockets คำถามที่ดี.

เหตุผลหนึ่งที่ SSE ถูกเก็บไว้ในเงามืดก็คือเพราะหลังจากนั้น APIs เช่น WebSockets จะมีโปรโตคอลที่สมบูรณ์ยิ่งขึ้นเพื่อทำการสื่อสารแบบสองทาง การมีแชนเนลแบบสองทางน่าสนใจยิ่งขึ้นสำหรับสิ่งต่าง ๆ เช่นเกมแอพส่งข้อความและในกรณีที่คุณต้องการใกล้การอัพเดตตามเวลาจริงทั้งสองทิศทาง อย่างไรก็ตามในบางสถานการณ์ข้อมูลไม่จำเป็นต้องถูกส่งจากลูกค้า คุณเพียงแค่ต้องการอัปเดตจากการกระทำของเซิร์ฟเวอร์ ตัวอย่างเล็ก ๆ น้อย ๆ ก็คือการอัพเดทสถานะของเพื่อนตัวเลือกหุ้นฟีดข่าวหรือกลไกการส่งข้อมูลอัตโนมัติอื่น ๆ (เช่นการอัพเดตฐานข้อมูล Web SQL ฝั่งไคลเอ็นต์หรือที่เก็บอ็อบเจ็กต์ IndexedDB) หากคุณต้องการส่งข้อมูลไปยังเซิร์ฟเวอร์ XMLHttpRequest จะเป็นเพื่อนเสมอ

SSE ถูกส่งผ่าน HTTP ดั้งเดิม นั่นหมายความว่าพวกเขาไม่ต้องการโปรโตคอลพิเศษหรือการติดตั้งเซิร์ฟเวอร์เพื่อให้ทำงานได้ ในขณะที่ WebSockets ต้องการการเชื่อมต่อ full-duplex และเซิร์ฟเวอร์ Web Socket ใหม่เพื่อจัดการโปรโตคอล นอกจากนี้เหตุการณ์ที่เซิร์ฟเวอร์ส่งมีความหลากหลายของคุณสมบัติที่ WebSockets ขาดโดยการออกแบบเช่นการเชื่อมต่อใหม่โดยอัตโนมัติ, ID เหตุการณ์และความสามารถในการส่งเหตุการณ์โดยพลการ


สรุป TLDR:

ข้อดีของ SSE ผ่าน Websockets:

  • ส่งผ่าน HTTP อย่างง่ายแทนที่จะเป็นโปรโตคอลที่กำหนดเอง
  • สามารถเติมโพลีด้วย javascript เป็น "backport" SSE ไปยังเบราว์เซอร์ที่ยังไม่รองรับ
  • สร้างขึ้นเพื่อรองรับการเชื่อมต่อใหม่และรหัสเหตุการณ์
  • โปรโตคอลที่เรียบง่าย
  • ไม่มีปัญหากับไฟร์วอลล์ขององค์กรที่ทำการตรวจสอบแพ็คเก็ต

ข้อดีของ Websockets ผ่าน SSE:

  • เรียลไทม์การสื่อสารสองทิศทาง
  • สนับสนุนพื้นเมืองในเบราว์เซอร์เพิ่มเติม

กรณีใช้ในอุดมคติของ SSE:

  • สตรีมมิ่งหุ้น
  • อัปเดตฟีด Twitter
  • การแจ้งเตือนไปยังเบราว์เซอร์

SSE gotchas:

  • ไม่มีการสนับสนุนไบนารี
  • ขีด จำกัด การเชื่อมต่อเปิดสูงสุด

131
การแชททำได้อย่างสมบูรณ์แบบด้วย SSE - คุณสามารถใช้ POST ปกติเพื่อส่งข้อความไปยังเซิร์ฟเวอร์ จะต้องใช้ WebSockets ต่อเมื่อคุณใช้การแชท a'la Google Wave
Kornel

135
เป็นความจริงที่การแชทและแอปพลิเคชันเรียลไทม์อื่น ๆ สามารถทำได้กับ SSE อย่างไรก็ตามสิ่งนี้ต้องการการตอบกลับ POSTing "out of band" ซึ่งไม่ได้ควบคุมโดยโปรโตคอล SSE และดูเหมือนจะไม่เป็นตัวอย่างที่ดีสำหรับคำอธิบายพื้นฐานเกี่ยวกับความแตกต่างระหว่าง SSE และ Websockets คุณสามารถใช้การแชทด้วย HTTP พื้นฐานในการโพลเซิร์ฟเวอร์ทุก ๆ วินาทีและโพสต์คำตอบใหม่ นี่ไม่ได้หมายความว่ามันเป็นวิธีที่ดีที่สุดในการทำ
อเล็กซ์ Recarey

14
ฉันคิดว่าทางออกของ pomeL นั้นเป็นวิธีที่ดีสำหรับกรณีส่วนใหญ่เนื่องจาก JS สามารถ "ผลัก" สิ่งต่าง ๆ ไปยังเซิร์ฟเวอร์ด้วย AJAX POST จากประสบการณ์ของฉันประเด็นสำคัญคือความต้องการ JS ในการสำรวจความคิดเห็นสำหรับข้อมูลใหม่ แต่ SSE ดูแลเรื่องนี้ : D
Jacob Pritchett

12
@MattDiPasquale Wave ส่งทุกคีย์แยกตามที่คุณพิมพ์แทนที่จะเป็นข้อความที่สมบูรณ์ในครั้งเดียว ค่าใช้จ่าย 200 ไบต์ของ POST สำหรับการกดแป้น 1 ครั้งจะสิ้นเปลืองเมื่อเทียบกับประมาณ 6 สำหรับ WebSocket
Kornel

9
ดูเหมือนแปลกเล็กน้อยที่จะบอกว่าพวกเขาไม่ได้เป็นเทคโนโลยีการแข่งขันและจากนั้นดำเนินการเพื่ออธิบายว่าพวกเขาสามารถนำมาใช้เพื่อให้ได้โซลูชั่นที่คล้ายกัน ฉันจะบอกว่าทำให้พวกเขาแข่งขัน
อเล็กซ์

115

ตามที่ caniuse.com:

คุณสามารถใช้ polyfill แบบไคลเอ็นต์เท่านั้นเพื่อขยายการสนับสนุน SSE ไปยังเบราว์เซอร์อื่น ๆ อีกมากมาย กรณีนี้น่าจะมีน้อยกว่าด้วย WebSockets Polyfills ของ EventSource บางส่วน:

  • EventSourceโดย Remy Sharp ที่ไม่มีการพึ่งพาไลบรารีอื่น ๆ (IE7 +)
  • jQuery.EventSourceโดย Rick Waldron
  • EventSourceโดยYaffle (แทนที่การใช้งานจริง, ปรับพฤติกรรมการทำงานข้ามเบราว์เซอร์)

หากคุณต้องการสนับสนุนเบราว์เซอร์ทั้งหมดให้พิจารณาใช้ห้องสมุดเช่นweb-socket-js , SignalRหรือsocket.ioซึ่งรองรับการถ่ายโอนหลายรายการเช่น WebSockets, SSE, Forever Frame และ AJAX long polling สิ่งเหล่านี้มักจะต้องการการแก้ไขฝั่งเซิร์ฟเวอร์เช่นกัน

เรียนรู้เพิ่มเติมเกี่ยวกับ SSE จาก:

เรียนรู้เพิ่มเติมเกี่ยวกับ WebSockets จาก:

ความแตกต่างอื่น ๆ :

  • WebSockets รองรับข้อมูลไบนารีโดยพลการ SSE ใช้ UTF-8 เท่านั้น

3
ฉันต้องการจะชี้ให้เห็นในปี 2559> 95% ของผู้ใช้ทั่วโลกสนับสนุน WebSockets เบราว์เซอร์และอุปกรณ์ทั้งหมดรองรับ WebSockets นานกว่า 4 ปี Socket.IO จะย้อนกลับไปยังการโพลแบบยาวของ AJAX และจัดการกับความซับซ้อนของการจำลอง WebSockets ให้คุณหากไม่รองรับซึ่งจะรองรับ 100% หากคุณใช้อะไรก็ตามยกเว้น WebSockets ในปี 2559 คุณกำลังใช้เทคโนโลยีที่ล้าสมัย
Nick Steele

3
@NickSteele นั่นคือคำแถลง hype ที่น่ารังเกียจ การใช้มาตรฐานที่เก่ากว่านั้นใช้ได้อย่างสมบูรณ์แบบหากพวกเขาตรงกับกรณีการใช้งานของคุณและไม่ได้หมายความว่าอะไรจะล้าสมัย มันเป็นแค่มาตรฐานที่แตกต่าง ตัวอย่าง: XHR ยังคงสามารถทำสิ่งต่างๆมากมายที่ Fetch API ไม่สามารถทำได้ดังนั้นจึงไม่ล้าสมัย มันแตกต่าง. ฉันเคยใช้ WS ในอดีต แต่รู้จากประสบการณ์ว่าสามารถดัก snags ในรูปแบบของไฟร์วอลล์เสียงองค์กรที่บล็อกการร้องขอเมื่อมันไม่เข้าใจ WS SSE นั้นมีประสิทธิภาพสูงสุดสำหรับสิ่งที่ทำสามารถเข้าใจได้ง่ายและสามารถนำไปใช้งานได้และง่ายต่อการดีบัก สำหรับดาต้าโฟลว์ทางเดียวของเรามันสมบูรณ์แบบ
oligofren

@ oligofren ไม่จำเป็นต้องสาบาน หากสิ่งที่ถูกออกแบบมาเพื่อแทนที่รุ่นก่อนหน้าและเป็นที่ยอมรับของอุตสาหกรรมและดีกว่าในทุก ๆ ด้านตามคำนิยามวิธีเก่าจะล้าสมัย เช่นเดียวกับ iPhone ดั้งเดิมที่ล้าสมัยดังนั้น XHR XHR ออกมาก่อน Firefox, Chrome, iPhone เครื่องแรก, ต่อ YouTube, Netflix, Facebook และแม้แต่ MySpace เมื่อ XHR ออกมา Windows 98 เป็นระบบปฏิบัติการที่ดีที่สุด AOL เป็นผู้ให้บริการที่ดีที่สุดและ JSON ไม่มีอยู่จริง WebSockets แทนที่ XHR เมื่อเกือบหนึ่งทศวรรษที่แล้ว หากคุณกดอุปสรรค์โดยใช้ WS สิ่งที่ทำให้อุปสรรค์ล้าสมัยเช่นกัน ไม่มีข้อแก้ตัวสำหรับความล่าช้านั้น
Nick Steele

4
แทนที่ BS ด้วยอติพจน์แล้ว :-) WS ไม่ใช่การแทนที่ XHR / HTTP มากกว่าโดรนสำหรับการส่งมอบรถยนต์ มันเป็นกรณีการใช้งานที่แตกต่างกัน WS ไม่ใช่ HTTP และมีจุดที่แตกต่างกัน คุณจะต้องปรับใช้ HTTP (ไม่ดี) ในพื้นที่ผู้ใช้อีกครั้งหากคุณลอง นอกจากนี้คุณกำลังแสดงถึงสิ่งที่ไม่ได้ให้ข้อเท็จจริง: WS เป็นเพียงโปรโตคอลสองทิศทางที่สนับสนุนการพุชเซิร์ฟเวอร์ ฉันไม่เคยเห็นเอกสารการออกแบบใด ๆ ที่กล่าวถึงว่าได้รับการพัฒนาเพื่อทดแทนสิ่งใด แหล่งที่มา? อายุในตัวมันเองไม่ใช่ปัจจัย เมื่อได้รับตัวเลือกให้เลือกการใช้งานที่ง่ายที่สุดที่ตรวจสอบความต้องการของคุณทั้งหมด
oligofren

1
เป็นเพียงสองปีที่ผ่านมา (2017) ฉันได้แก้จุดบกพร่องกองทิ้งของกระบวนการ Node JS ที่รหัส Socket.io ทำให้เกิดการแตกหน่วยความจำขนาดใหญ่ในกระบวนการ IIS จบลงด้วยการพูดคุยโดยตรงกับทีมโหนด Azure ของ Azure ความซับซ้อนทั้งหมดไม่ได้ฟรี หากคุณสามารถออกไปกับสคริปต์ 20 บรรทัดที่เรียบง่ายเป็นการอ้างอิงของคุณบนเซิร์ฟเวอร์ในขณะที่ยังสามารถให้บริการลูกค้า 100K ฉันจะไปได้ ฉันชอบ WS สำหรับสิ่งที่มันทำ แต่ดูที่สิ่งที่คุณต้องการก่อนที่จะเลือกวิธีการแก้ปัญหา
oligofren

16

Opera, Chrome, Safari รองรับ SSE, Chrome, Safari รองรับ SSE ภายใน SharedWorker Firefox รองรับ XMLHttpRequest readyState แบบโต้ตอบดังนั้นเราจึงสามารถสร้าง EventSource polyfil สำหรับ Firefox


8

Websocket VS SSE


Web Sockets -เป็นโปรโตคอลที่ให้ช่องทางการสื่อสาร full-duplex ผ่านการเชื่อมต่อ TCP เดียว ตัวอย่างเช่นการสื่อสารสองทางระหว่างเซิร์ฟเวอร์และเบราว์เซอร์เนื่องจากโปรโตคอลมีความซับซ้อนมากขึ้นเซิร์ฟเวอร์และเบราว์เซอร์จะต้องพึ่งพาไลบรารีของ websocket ซึ่งเป็นsocket.io

Example - Online chat application.

SSE (เหตุการณ์ที่เซิร์ฟเวอร์ส่ง) - ในกรณีที่เซิร์ฟเวอร์ส่งเหตุการณ์การสื่อสารจะดำเนินการจากเซิร์ฟเวอร์ไปยังเบราว์เซอร์เท่านั้นและเบราว์เซอร์ไม่สามารถส่งข้อมูลใด ๆ ไปยังเซิร์ฟเวอร์ การสื่อสารประเภทนี้ส่วนใหญ่จะใช้เมื่อต้องการเพียงเพื่อแสดงข้อมูลที่ปรับปรุงแล้วเซิร์ฟเวอร์จะส่งข้อความเมื่อใดก็ตามที่ข้อมูลได้รับการปรับปรุง ตัวอย่างเช่นการสื่อสารทางเดียวระหว่างเซิร์ฟเวอร์กับเบราว์เซอร์ โพรโทคอลนี้มีความซับซ้อนน้อยลงดังนั้นไม่จำเป็นต้องพึ่งพาไลบรารีภายนอก JAVASCRIPT เองจึงจัดเตรียมEventSourceอินเตอร์เฟสเพื่อรับข้อความที่เซิร์ฟเวอร์ส่ง

Example - Online stock quotes or cricket score website.

4

สิ่งหนึ่งที่ควรทราบ:
ฉันมีปัญหากับ websockets และไฟร์วอลล์ขององค์กร (การใช้ HTTPS ช่วยได้ แต่ไม่เสมอไป)

ดูhttps://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software https://github.com/sockjs/sockjs-client/issues/94

ฉันคิดว่ามีปัญหาไม่มากกับ Server-Sent Events แต่ฉันไม่รู้

ที่กล่าวว่า WebSockets สนุกมาก ฉันมีเกมบนเว็บเล็กน้อยที่ใช้ websockets (ผ่าน Socket.IO) ( http://minibman.com )


1
ฉันยังมีปัญหากับไฟร์วอลล์ขององค์กร
oligofren

1
ปัญหาหนึ่งที่ฉันเห็นด้วยเหตุการณ์ที่เซิร์ฟเวอร์ส่งคือพร็อกซี / ไฟร์วอลล์บางตัวอาจบล็อกเนื่องจากมีส่วนหัวความยาวเนื้อหา
Drew LeSueur

2

นี่คือการพูดคุยเกี่ยวกับความแตกต่างระหว่างเว็บซ็อกเก็ตและเซิร์ฟเวอร์ที่ส่งเหตุการณ์ ตั้งแต่ Java EE 7 WebSocket API เป็นส่วนหนึ่งของสเปคแล้วและดูเหมือนว่าเซิร์ฟเวอร์ที่ส่งเหตุการณ์จะออกในรุ่นถัดไปของรุ่นองค์กร


-3

ขีด จำกัด การเชื่อมต่อสูงสุดไม่ใช่ปัญหาของ http2 + sse

มันเป็นปัญหาใน http 1


Http2 อนุญาตให้คำขอหลายรายการในโดเมนเดียวกันถือเป็นสตรีม เทคนิคนี้เรียกว่ามัลติเพล็กซ์ วิธีนี้ช่วยประหยัดขีด จำกัด ของการเชื่อมต่อเบราว์เซอร์ต่อโดเมนซึ่งเป็นเหตุผลว่าทำไมผู้คนจึงใช้งานโดเมนร่วมกับ Http1
user1948585

1
HTTP / 2 สตรีมก็มีจำนวน จำกัด เช่นนี้จะช่วยป้องกันเซิร์ฟเวอร์จากการถูกโจมตีโดยเบราว์เซอร์เดียวและบังคับให้เบราว์เซอร์ จำกัด จำนวนมัลติเพล็กซ์ของสตรีมไปยังสตรีมจำนวน จำกัด ซึ่งในกรณีของเรานั้นเหมือนกับการเชื่อมต่อ HTTP / 1.1 .. . ซึ่งนำคุณกลับสู่ขีด จำกัด การเชื่อมต่อ SSE
Myst

ฉันถือว่าการเชื่อมต่อ websocket ใช้ทรัพยากรเซิร์ฟเวอร์ด้วย samsaffron.com/archive/2015/12/29/websockets-caution-required มันดีเสมอที่จะมีความสามารถในการกำหนดค่าให้มากที่สุดเท่าที่กระเป๋าของคุณอนุญาต
user1948585

เป็นไปได้ว่า SSE จะใช้ทรัพยากรที่คล้ายกันในเซิร์ฟเวอร์ส่วนใหญ่ (หากไม่มีทรัพยากรเพิ่มเติมเนื่องจาก HTTP stack ที่ยังคงอยู่และมีข้อ จำกัด )
Myst

1
คำตอบนี้ถูกต้อง ขีด จำกัด ของการเชื่อมต่อ HTTP 6 ไม่มีอยู่อีกต่อไปเมื่อใช้ HTTP / 2 หลักฐาน: codepen.io/dunglas/pen/yLYxdxK?editors=1010 ด้วย HTTP / 2 มันเป็นเซิร์ฟเวอร์และลูกค้าสามารถเจรจาจำนวนสูงสุดของกระแสพร้อมกัน (100 โดยค่าเริ่มต้น)
Kévin Dunglas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.