HTTP / 2 ทำให้ websockets ล้าสมัยหรือไม่


268

ฉันเรียนรู้เกี่ยวกับโปรโตคอล HTTP / 2 มันเป็นโปรโตคอลเลขฐานสองที่มีเฟรมข้อความขนาดเล็ก ช่วยให้การสตรีมมัลติเพล็กซ์ผ่านการเชื่อมต่อ TCP เดียว แนวคิดดูเหมือนว่าคล้ายกันมากกับ WebSockets

มีแผนการที่จะล้าสมัย websockets และแทนที่ด้วยคำขอ HTTP / 2 headerless บางชนิดและข้อความพุชที่เริ่มต้นโดยเซิร์ฟเวอร์หรือไม่ WebSockets หรือจะเติมเต็ม HTTP / 2 หรือไม่


ฉันคิดว่าคำตอบที่ยอมรับนั้นถูกต้อง websockets ยังคงเป็นทางออกที่ดีสำหรับเว็บแอปพลิเคชันในการสื่อสารกับเซิร์ฟเวอร์แบบสองทิศทางรวมถึงข้อความที่ส่งจากเซิร์ฟเวอร์ HTTP ถูกใช้มากกว่าเบราว์เซอร์และเมื่อทั้งไคลเอนต์และเซิร์ฟเวอร์สามารถใช้ API ระดับต่ำพวกเขาไม่ต้องการ websockets คนส่วนใหญ่ยังใช้ HTTP สำหรับเว็บแอปพลิเคชันและส่วนใหญ่กังวลเกี่ยวกับ API ที่เปิดเผยโดย JavaScript หากผู้ดำเนินรายการคิดว่าคำตอบที่ได้รับการยอมรับควรแตกต่างกันฉันไม่ได้คัดค้านเพราะคำถามนี้ทำให้เกิดความคิดเห็นมากมายและความคิดเห็นของฉันอาจผิด
vbezhenar

คำตอบ:


161

จากสิ่งที่ฉันเข้าใจ HTTP / 2 ไม่ใช่การแทนที่ websocket แต่มีจุดมุ่งหมายเพื่อสร้างมาตรฐานโปรโตคอล SPDY

ใน HTTP / 2 เซิร์ฟเวอร์จะใช้การผลักดันเบื้องหลังเพื่อปรับปรุงการโหลดทรัพยากรโดยไคลเอนต์จากเบราว์เซอร์ ในฐานะนักพัฒนาคุณไม่สนใจเรื่องนี้ในระหว่างการพัฒนา อย่างไรก็ตามด้วย Websocket นักพัฒนาซอฟต์แวร์ได้รับอนุญาตให้ใช้ API ซึ่งสามารถใช้งานและส่งข้อความด้วยการเชื่อมต่อ full-duplex ที่เป็นเอกลักษณ์

สิ่งเหล่านี้ไม่เหมือนกันและควรเสริมซึ่งกันและกัน


3
ขอบคุณ Guillaume สำหรับคำตอบของคุณ อย่างไรก็ตามฉันสงสัยว่าคุณ (หรือบางคน) สามารถเพิ่มการอ้างอิงบางส่วนจากสเปค HTTP / 2 สิ่งที่ฉันได้อ่านจากบล็อกและอื่น ๆ - ด้วย HTTP / 2 มีการสื่อสารแบบสองทิศทางที่แท้จริงคืออะไร?
Martin Meeser

3
ไม่แน่ใจว่าข้อมูลจำเพาะ HTTP / 2 เป็นสถานที่ที่เหมาะสมในการให้รายละเอียดเกี่ยวกับต้นกำเนิดของ HTTP / 2 และวิธีการที่แตกต่างจาก websocket อย่างไรก็ตามคุณสามารถเห็นได้อย่างง่ายดายด้วย HTTP / 2 เราใช้การสื่อสารแบบสองทิศทาง: goo.gl/IJVxWS (หน้า 6 และ 13)
Guillaume D.

27
HTTP / 2 นั้นเป็นแบบสองทิศทาง แต่ไม่ใช่แบบสมมาตรซึ่งหมายความว่ามีเพียงลูกค้าเท่านั้นที่สามารถส่งคำขอที่เหมาะสมและเซิร์ฟเวอร์สามารถส่งคำตอบและขอสัญญา (push) สิ่งนี้ทำให้เว็บกระเป๋ามีความแตกต่างในแง่ที่ว่าทั้งสองฝ่ายมีความ "เท่าเทียมกัน" มากกว่าในแง่ของสิ่งที่พวกเขาได้รับอนุญาตให้ส่ง / รับ
George Antoniadis

3
มีพอดคาสต์ที่ยอดเยี่ยมในวิทยุวิศวกรรมซอฟต์แวร์ของ IEEE เกี่ยวกับต้นกำเนิดของ HTTP2 ฉันคิดว่ามันคือ: se-radio.net/2015/07/episode-232-mark-nottingham-on-http2
Max Murphy

2
คำตอบที่คล้ายกันกับเหตุผลเต็มสามารถพบได้ในบทความ InfoQ ที่นี่: infoq.com/articles/websocket-and-http2-coexist
mantrid

151

หลังจากอ่านข้อมูลจำเพาะ HTTP / 2เสร็จแล้วฉันคิดว่า HTTP / 2 นั้นล้าสมัย websockets สำหรับกรณีการใช้งานส่วนใหญ่ แต่อาจไม่ทั้งหมด

PUSH_PROMISE(เรียกขานกันว่าการพุชเซิร์ฟเวอร์) ไม่ใช่ปัญหาที่นี่ นั่นเป็นเพียงการเพิ่มประสิทธิภาพ

กรณีการใช้งานหลักสำหรับ Websockets ในเบราว์เซอร์คือการเปิดใช้งานการสตรีมข้อมูลแบบสองทิศทาง ดังนั้นฉันคิดว่าคำถามของ OP จะกลายเป็นว่า HTTP / 2 ทำงานได้ดีกว่าในการเปิดใช้งานการสตรีมแบบสองทิศทางในเบราว์เซอร์และฉันคิดว่าใช่

อย่างแรกเลยคือ bi-di เพียงอ่านบทนำสู่ส่วนของสตรีม :

"สตรีม" เป็นลำดับที่เป็นอิสระและเป็นแบบสองทิศทางของการแลกเปลี่ยนเฟรมระหว่างไคลเอนต์และเซิร์ฟเวอร์ภายในการเชื่อมต่อ HTTP / 2 ลำธารมีลักษณะสำคัญหลายประการ:

การเชื่อมต่อ HTTP / 2 เดียวสามารถมีสตรีมที่เปิดหลายแห่งพร้อมกันโดยมีจุดปลาย interleaving เฟรมจากหลายสตรีม

สตรีมสามารถสร้างและใช้เพียงฝ่ายเดียวหรือใช้ร่วมกันโดยไคลเอนต์หรือเซิร์ฟเวอร์

สตรีมสามารถปิดได้โดยอุปกรณ์ปลายทาง

บทความเช่นนี้ (เชื่อมโยงกับคำตอบอื่น) ผิดเกี่ยวกับแง่มุมของ HTTP / 2 นี้ พวกเขาบอกว่ามันไม่ใช่ bidi ดูมีสิ่งหนึ่งที่ไม่สามารถเกิดขึ้นได้กับ HTTP / 2: หลังจากเปิดการเชื่อมต่อเซิร์ฟเวอร์จะไม่สามารถเริ่มสตรีมปกติเพียงสตรีมแบบพุชเท่านั้น แต่เมื่อลูกค้าเปิดสตรีมด้วยการส่งคำขอทั้งสองฝ่ายสามารถส่งเฟรมข้อมูลไปยังซ็อกเก็ตแบบถาวรได้ตลอดเวลา - เต็มเต็ม

นั่นไม่ได้แตกต่างจาก websockets มากนัก: ลูกค้าต้องเริ่มต้นคำขออัพเกรด websocket ก่อนที่เซิร์ฟเวอร์จะสามารถส่งข้อมูลได้เช่นกัน

ความแตกต่างที่ใหญ่ที่สุดคือ HTTP / 2 จะกำหนดความหมายเชิงมัลติเพล็กซ์ของตัวเองซึ่งแตกต่างจาก websockets คือวิธีที่สตรีมได้รับตัวระบุและวิธีที่เฟรมนำเสนอไอดีของสตรีมที่อยู่บนนั้น HTTP / 2 ยังกำหนด semantics ควบคุมการไหลสำหรับการจัดลำดับความสำคัญลำธาร นี่เป็นสิ่งสำคัญในแอปพลิเคชัน bidi ที่ใช้งานจริง

(บทความที่ผิดยังบอกว่ามาตรฐาน Websocket มีมัลติเพล็กซ์ไม่มันไม่ยากเลยที่จะหามันแค่เปิด Websocket RFC 6455และกด⌘-F แล้วพิมพ์ "มัลติเพล็กซ์" หลังจากอ่านแล้ว

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

คุณจะพบว่ามีส่วนขยายร่าง 2013 สำหรับการทำมัลติเพล็กซิ่ง Websocket แต่ฉันไม่ทราบว่ามีเบราว์เซอร์ใดบ้างที่สนับสนุน ฉันจะไม่พยายามสร้าง webapp SPA ของฉันที่ด้านหลังของส่วนขยายนั้นโดยเฉพาะอย่างยิ่งเมื่อมี HTTP / 2 มาการสนับสนุนอาจไม่มาถึง)

การทำ Multiplexing เป็นสิ่งที่คุณต้องทำด้วยตัวเองทุกครั้งที่คุณเปิด websocket สำหรับ bidi พูดเพื่อเพิ่มประสิทธิภาพให้แอพพลิเคชั่นหน้าเดียวแบบโต้ตอบ ฉันดีใจที่มันอยู่ในข้อมูลจำเพาะ HTTP / 2 ได้รับการดูแลทันทีและทั้งหมด

ถ้าคุณต้องการทราบว่า HTTP / 2 สามารถทำอะไรได้แค่ดู gRPC gRPC ถูกนำไปใช้กับ HTTP / 2 ดูตัวเลือกการสตรีมมิ่งครึ่งและเต็มเพล็กซ์ที่ gRPC นำเสนอโดยเฉพาะ (โปรดทราบว่าขณะนี้ gRPC ไม่สามารถใช้งานได้ในเบราว์เซอร์ แต่นั่นเป็นเพราะเบราว์เซอร์ (1) ไม่เปิดเผยเฟรม HTTP / 2 ไปยังไคลเอ็นต์ javascript และ (2) ไม่สนับสนุนตัวอย่างทั่วไปซึ่งใช้ใน ข้อมูลจำเพาะ gRPC)

เว็บซ็อคเก็ตอาจจะมีที่ไหน เบราว์เซอร์ตัวใหญ่คือเซิร์ฟเวอร์ -> เบราว์เซอร์ผลักข้อมูลไบนารี HTTP / 2 อนุญาตให้เซิร์ฟเวอร์ -> เบราว์เซอร์ผลักข้อมูลไบนารี แต่จะไม่เปิดเผยในเบราว์เซอร์ JS สำหรับแอปพลิเคชันเช่นการผลักเฟรมเสียงและวิดีโอนี่คือเหตุผลที่ใช้เว็บซ็อกเก็ต

แก้ไข: Jan 17 2020

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

ในการสรุป: โปรโตคอล HTTP / 2 นั้นเต็มไปด้วยสองส่วน อย่างไรก็ตามเว็บเบราว์เซอร์ที่ทันสมัยอย่าให้กรอบเชิง HTTP / 2 โปรโตคอล JavaScript ไม่อย่างนั้นถ้าคุณทำการร้องขอหลายครั้งไปยังจุดกำเนิดเดียวกันผ่านการเชื่อมต่อ HTTP / 2 ภายใต้ประทุนการรับส่งข้อมูลทั้งหมดนั้นได้รับการเชื่อมต่อแบบหลายจุดในการเชื่อมต่อเดียว (และนั่นคือสิ่งที่เราใส่ใจ!)

ดังนั้นหากคุณต้องการสร้างแอปแชทเรียลไทม์สมมติว่าคุณต้องการถ่ายทอดข้อความแชทใหม่ให้กับลูกค้าทุกคนในห้องสนทนาที่มีการเชื่อมต่อแบบเปิดคุณสามารถทำได้

คุณจะใช้เหตุการณ์ที่ส่งโดยเซิร์ฟเวอร์เพื่อส่งข้อความลงและFetch api เพื่อส่งคำขอ เหตุการณ์ที่เซิร์ฟเวอร์ส่ง (SSE) เป็นAPI ที่รู้จักกันน้อย แต่ได้รับการสนับสนุนเป็นอย่างดีซึ่งทำให้มีการสตรีมเซิร์ฟเวอร์กับไคลเอ็นต์ แม้ว่ามันจะดูไม่เหมือนกับ JavaScript ของไคลเอ็นต์ แต่ภายใต้ฮูดเบราว์เซอร์ของคุณ (หากรองรับ HTTP / 2) จะใช้การเชื่อมต่อ TCP เดียวเพื่อนำข้อความทั้งหมดเหล่านี้กลับมาใช้ซ้ำอีกครั้ง ไม่มีการสูญเสียประสิทธิภาพและในความเป็นจริงมันได้รับมากกว่า websockets ต้องการสตรีมหลายรายการหรือไม่ เปิด EventSources หลายรายการ! พวกเขาจะถูก multiplexed โดยอัตโนมัติสำหรับคุณ

นอกเหนือจากการใช้ทรัพยากรอย่างมีประสิทธิภาพมากขึ้นและมีเวลาแฝงเริ่มต้นน้อยกว่าการจับมือกันของ websocket เหตุการณ์ที่เซิร์ฟเวอร์ส่งมีคุณสมบัติที่ดีที่พวกเขาย้อนกลับโดยอัตโนมัติและทำงานผ่าน HTTP / 1.1 แต่เมื่อคุณมีการเชื่อมต่อ HTTP / 2 มันทำงานได้ดีอย่างไม่น่าเชื่อ

นี่คือบทความที่ดีพร้อมตัวอย่างจริงของการทำสปาที่มีการปรับปรุงใหม่


21
คำตอบนี้ไม่เห็นด้วยกับคำตอบอื่น ๆ บางส่วนรวมถึงคำตอบที่ยอมรับและเป็นคำตอบที่ดีที่สุดเพราะขึ้นอยู่กับแหล่งที่มาโดยตรง
sudo

7
ฉันเห็นด้วยอย่างยิ่งกับคำตอบและความคิดเห็นนี้ HTTP / 2 เป็นแบบสตรีมแบบสองทิศทาง
Martin Meeser

3
คำตอบที่ถูกต้องจริงคนที่แต่งตัวประหลาดใส่ใจในการตรวจสอบแหล่งที่มาและการประยุกต์ใช้โลกแห่งความจริง (grpc)
Vladimir Akopyan

1
ในเว็บซ็อกเก็ตเซิร์ฟเวอร์ไม่สามารถเริ่มการส่งข้อมูลแบบสุ่มได้จนกว่าไคลเอ็นต์จะเริ่มต้นคำขออัปเกรด websocket แต่ก็สามารถกดได้ตลอดเวลา ใน HTTP / 2 เซิร์ฟเวอร์จะไม่สามารถเริ่มการส่งข้อมูลแบบพุชได้จนกว่าไคลเอ็นต์จะเริ่มการเชื่อมต่อข้อมูล แต่จากนั้นจะสามารถส่งข้อมูลแบบไบต์ได้ตลอดเวลา ความแตกต่างด้านหน้าที่คืออะไร ดังที่ฉันได้ชี้ให้เห็นว่าความสามารถ PUSH_PROMISE เป็นปลาเฮอริ่งแดง ไม่ใช่เหตุผลที่ HTTP / 2 นั้นมาแทนที่เว็บซ็อกเก็ต เป็นเพียงการเพิ่มประสิทธิภาพเล็กน้อยไปทางด้านข้าง มันไม่มีส่วนเกี่ยวข้องกับหัวใจของ HTTP / 2 ซึ่งเป็นสตรีมมิ่ง bidi
masonk

1
คำตอบนี้เป็นเพียงความผิด มันทำให้เกิดความสับสนหลายแง่มุมที่ทำให้สับสน อย่างไรก็ตามประเด็นสำคัญของเรื่องนี้ก็คือกระแสข้อมูล HTTP / 2 "bidi" นั้นเป็นตัวขับเคลื่อนการตอบสนองการร้องขอ (และมีจำนวน จำกัด ) ในขณะที่โปรโตคอล WebSockets เป็นข้อความจริงที่ใช้โปรโตคอล bidi (ไม่ใช่การตอบสนองตามคำขอ ยกเว้นช่วงจับมือ) นี่เป็นความแตกต่างอย่างมากที่ไม่สามารถเชื่อมโยงได้โดยการอ่านข้อกำหนดที่ไม่ถูกต้อง (เนื่องจาก @masonk ปรากฏขึ้นโดยไม่ได้ตั้งใจ)
Myst

64

ฉันบอกว่าไม่ ( เว็บซ็อกเก็ตไม่ล้าสมัย )

ปัญหาแรกและบ่อยที่สุดที่ถูกเพิกเฉยคือHTTP / 2 push ไม่สามารถบังคับใช้ได้และอาจถูกละเว้นโดยผู้รับมอบฉันทะเราเตอร์ตัวกลางอื่นหรือแม้แต่เบราว์เซอร์

ie (จากแบบร่าง HTTP2):

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

ดังนั้น HTTP / 2 Push ไม่สามารถแทนที่ WebSockets

นอกจากนี้การเชื่อมต่อ HTTP / 2 จะปิดหลังจากนั้นไม่นาน

เป็นความจริงที่มาตรฐานระบุว่า:

การเชื่อมต่อ HTTP / 2 จะคงอยู่ เพื่อประสิทธิภาพที่ดีที่สุดคาดว่าลูกค้าจะไม่ปิดการเชื่อมต่อจนกว่าจะพบว่าไม่จำเป็นต้องสื่อสารกับเซิร์ฟเวอร์เพิ่มเติม (ตัวอย่างเช่นเมื่อผู้ใช้นำทางออกจากหน้าเว็บเฉพาะ) หรือจนกว่าเซิร์ฟเวอร์จะปิดการเชื่อมต่อ

แต่...

เซิร์ฟเวอร์ได้รับการสนับสนุนให้รักษาการเชื่อมต่อที่เปิดไว้ให้นานที่สุดแต่จะได้รับอนุญาตให้ยุติการเชื่อมต่อที่ไม่ได้ใช้งานหากจำเป็น เมื่อปลายทางเลือกที่จะปิดการเชื่อมต่อ TCP เลเยอร์การขนส่งจุดสิ้นสุดที่สิ้นสุดควรส่งเฟรม GOAWAY (มาตรา 6.8) ก่อนเพื่อให้จุดสิ้นสุดทั้งสองนั้นสามารถกำหนดได้อย่างน่าเชื่อถือว่าเฟรมที่ส่งไปก่อนหน้านี้ได้รับการประมวลผลแล้ว

แม้ว่าการเชื่อมต่อเดียวกันจะอนุญาตให้มีการผลักดันเนื้อหาในขณะที่เปิดอยู่และแม้ว่า HTTP / 2 จะแก้ปัญหาด้านประสิทธิภาพที่แนะนำโดย HTTP / 1.1 ของ 'Keep-alive' ... การเชื่อมต่อ HTTP / 2 จะไม่เปิดตลอดไป .

หรือหน้าเว็บไม่สามารถเริ่มต้นการเชื่อมต่อ HTTP / 2 อีกครั้งเมื่อปิด (ยกเว้นว่าเรากลับไปที่การดึงแบบยาวนั่นก็คือ)

แก้ไข (2017 สองปีต่อมา)

การใช้งาน HTTP / 2 แสดงให้เห็นว่าแท็บเบราว์เซอร์หลายตัว / windows ใช้การเชื่อมต่อ HTTP / 2 เดียวซึ่งหมายความว่าpushจะไม่มีทางรู้ว่ามันเป็นแท็บ / หน้าต่างใดจึงไม่ใช้pushแทน Websockets

แก้ไข (2020)

ฉันไม่แน่ใจว่าทำไมคนเริ่ม downvoting คำตอบ หากมีสิ่งใดเป็นเวลาหลายปีตั้งแต่คำตอบถูกโพสต์ครั้งแรกพิสูจน์ว่า HTTP / 2 ไม่สามารถแทนที่ WebSockets และไม่ได้ออกแบบมาให้ทำเช่นนั้น

จริงอยู่ที่ HTTP / 2 อาจจะนำมาใช้เพื่ออุโมงค์เชื่อมต่อ WebSocket แต่การเชื่อมต่ออุโมงค์เหล่านี้จะยังคงต้องใช้โปรโตคอล WebSocket และพวกเขาจะมีผลกระทบต่อทาง HTTP / 2 พฤติกรรมภาชนะ


4
ซ็อกเก็ต WS จะไม่เปิดตลอดไป ความแตกต่างคือลำธาร; HTTP / 2 ช่วยให้คุณมีกระแสหลายกระแสซึ่งหมายความว่าการควบคุมการไหลบนเซิร์ฟเวอร์ที่แตกต่างกันมากและมักจะล็อค WS (เป็นโปรโตคอล) จะต้องมีการประมวลผลขาเข้าที่ไม่ได้ควบคุม การควบคุมการไหลถูกนำมาใช้สูงขึ้นสแต็ค เพื่อความปลอดภัยและความสมบูรณ์ของเซิร์ฟเวอร์ HTTP / 2 นั้นดีกว่า WS มาก
บอนด์

3
@bond ฉันยอมรับว่า HTTP / 2 มีข้อได้เปรียบมากมายในฐานะเลเยอร์การขนส่ง (การแชร์การเชื่อมต่อครั้งเดียวผ่านแท็บเบราว์เซอร์จำนวนมากเป็นเพียงตัวอย่างเดียว) แต่ก็ไม่ได้รับการออกแบบเป็นชั้นการสื่อสาร มันเป็นคำถามที่ใช้การได้ โปรโตคอลทั้งสองตอบสนองความต้องการที่แตกต่างกัน เช่นการนำsshเทอร์มินัลไปใช้กับเบราว์เซอร์นั้นเป็นเรื่องง่ายเมื่อใช้งาน Websockets มันจะปวดหัวโดยรวมใน HTTP / 2 โดยเฉพาะถ้ามีมากกว่าหนึ่งแท็บที่เปิดอยู่ นอกจากนี้จะเกิดอะไรขึ้นถ้าเบราว์เซอร์ (หรือหนึ่งในผู้รับมอบฉันทะ HTTP / 2) ปิดการเชื่อมต่อ? ลูกค้าสามารถสมมติว่าไม่มีข้อมูลใหม่ได้หรือไม่ เรากลับไปเลือกตั้ง
Myst

1
เบราว์เซอร์สามารถปิดการเชื่อมต่อ WS ของคุณได้อย่างง่ายดาย นั่นคือชีวิตที่มีเครือข่ายทุกชนิด ความซื่อสัตย์มัลติเพล็กซิ่งใน HTTP / 2 นั้นมากเกินไป โปรโตคอลไม่ต้องการมันจริงๆ ด้วยการเปิดสตรีมหลายรายการคุณจะเริ่มประสบปัญหากับบัฟเฟอร์ TCP จำกัด ปริมาณงาน ฉันเห็นด้วยกับคุณว่า WS ทำได้ดีกว่า HTTP / 2 โดยพื้นฐานแล้ว WS เป็นสิ่งที่ต้องการการควบคุมระดับที่สูงขึ้นมากมายเพื่อป้องกันผู้ใช้จากการทำสิ่งที่ไม่ดี
บอนด์

2
ในการอ้างถึงลุงเบ็น (สไปเดอร์ - แมน): "โปรดจำไว้ว่าพลังอันยิ่งใหญ่มาพร้อมความรับผิดชอบที่ยิ่งใหญ่" ใช่ @bond คุณพูดถูกมาก เว็บซ็อกเก็ตซึ่งเป็น "ดิบ" โปรโตคอลต้องมีการออกแบบเซิร์ฟเวอร์ที่รับผิดชอบมากขึ้น และใช่ WS สามารถปิดได้อย่างง่ายดายเหมือนกับ HTTP / 2 แต่ WS สนับสนุนการoncloseโทรกลับดังนั้นไม่จำเป็นต้องมีการสำรวจ สำหรับมัลติเพล็กซิ่งนั้นฉันคิดว่ามันเป็นความจำเป็น keep-aliveล้มเหลวและวิธีเดียวที่จะหลีกเลี่ยงการ "ประสิทธิภาพในบรรทัดแรก" คือการเสี่ยงต่อการทวีคูณ เวลาจะบอก :)
Myst

1
จากการออกแบบเซิร์ฟเวอร์ในมุมมองการมัลติเพล็กซ์ขาออกเป็นปัญหาที่ซับซ้อนและมีราคาแพง มันต้องใช้กลไก IO ในการสำรวจความคิดเห็นภายในซึ่งมีราคาแพงเหมือนนรก เว้นแต่ว่าคุณกำลังสตรีมเอกสารขนาดใหญ่การมัลติเพล็กซ์จะไม่ทำงานแม้กระทั่งเพราะคำขออาจตอบสนองและถูกบัฟเฟอร์ภายในอย่างสมบูรณ์ก่อนที่วินาทีจะพร้อมใช้งานและมัลติเพล็กซ์ล้มเหลวในการทำงาน RTMP มีมัลติเพล็กซ์ขาออก แต่เซิร์ฟเวอร์ของ Adobe เท่านั้นที่ทำได้ เป็นเรื่องที่น่าอัศจรรย์ว่า HTTP / 2 ใกล้เคียงกับ RTMP อย่างไร
บอนด์

39

คำตอบคือไม่ เป้าหมายระหว่างสองนั้นแตกต่างกันมาก มีแม้กระทั่ง RFC สำหรับ WebSocket ผ่าน HTTP / 2 ซึ่งช่วยให้คุณทำการเชื่อมต่อ WebSocket หลายการเชื่อมต่อผ่าน HTTP / 2 ไปป์ TCP เดียว

WS ผ่าน HTTP / 2 จะเป็นการอนุรักษ์ทรัพยากรโดยลดเวลาในการเปิดการเชื่อมต่อใหม่และอนุญาตให้มีช่องทางการสื่อสารมากขึ้นโดยไม่ต้องเสียค่าใช้จ่ายเพิ่มเติมของซ็อกเก็ต IRQ ที่อ่อนนุ่มและบัฟเฟอร์มากขึ้น

https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-01


ที่น่าตื่นตาตื่นใจ! มีตัวอย่างสาธารณะของไคลเอนต์ Javascript ซึ่งได้ดำเนินการนี้หรือไม่? ฉันไม่พบตัวอย่างใด ๆ ฉันต้องทำอะไร นี่เป็นทรัพยากรที่ดีหรือไม่? undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html
RaisinBranCrunch

ไม่มีใครรู้ว่าแหล่งที่มาของการเรียกร้องดังกล่าวประมาณ 1) การค้นหาความยาวของส่วนหัว 2) การลดชื่อเขตข้อมูลที่ลดลง?
Pim Heijden

@PimHeijden การตรวจสอบความยาวส่วนหัวใน HTTP / 1.x ต้องวนลูปผ่านไบต์ทั้งหมดที่ค้นหาเครื่องหมายจุดสิ้นสุด 4 ไบต์ นั่นแพงมาก ตัวพิมพ์เล็กของชื่อฟิลด์ยังหมายความว่าการจับคู่ฟิลด์ใด ๆ จะต้องทำสำหรับอักขระตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก สิ่งนี้ต้องมีความรู้เกี่ยวกับชุดอักขระทั้งหมดถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็กสำหรับการตรวจสอบ ใน 2.x คุณสามารถสมมติว่าเป็นตัวพิมพ์เล็ก
บอนด์

@RaisinBranCrunch คุณไม่สามารถควบคุมสิ่งนี้ได้จาก Javascript เบราว์เซอร์ทำทุกอย่างให้คุณ
บอนด์

@bond ฉันกำลังใช้ HTTP / 2 กับ Nginx และ proxy_pass เพื่อส่งการเชื่อมต่อ websocket ไปยังซ็อกเก็ตเซิร์ฟเวอร์ แต่เมื่อฉันมีผู้ใช้คนเดียวเปิดหลายแท็บในเว็บไซต์ซ็อกเก็ตเซิร์ฟเวอร์จะถือว่าเป็นการเชื่อมต่อหลายรายการ ฉันจะสมมติว่าถ้า HTTP / 2 เป็นการเชื่อมต่อแบบมัลติเพล็กซ์ผ่านไปป์ TCP หนึ่งเซิร์ฟเวอร์จะถือว่าเป็นหนึ่งการเชื่อมต่อ มันผิดหรือเปล่า? มีวิธีใดที่จะตรวจสอบว่าเซิร์ฟเวอร์ไม่ได้ทำการเชื่อมต่อที่ไม่จำเป็นเป็นพิเศษหรือไม่?
RaisinBranCrunch

23

อ้างจากบทความInfoQนี้:

คำตอบคือไม่ชัดเจนด้วยเหตุผลง่ายๆดังที่เราได้เห็นข้างต้น HTTP / 2 แนะนำ Server Push ซึ่งช่วยให้เซิร์ฟเวอร์ส่งทรัพยากรเชิงรุกไปยังแคชลูกค้า อย่างไรก็ตามไม่อนุญาตให้ส่งข้อมูลลงไปยังแอปพลิเคชันไคลเอนต์เอง เบราว์เซอร์ของเซิร์ฟเวอร์นั้นประมวลผลโดยเบราว์เซอร์เท่านั้นและไม่ปรากฏขึ้นในรหัสแอปพลิเคชันซึ่งหมายความว่าไม่มี API สำหรับแอปพลิเคชันที่จะรับการแจ้งเตือนสำหรับเหตุการณ์เหล่านั้น

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


5

การแลกเปลี่ยนข้อความและการสตรีมแบบง่าย ๆ (ไม่ใช่เสียง, การสตรีมวิดีโอ) สามารถทำได้ผ่านทั้ง Http / 2 multiplexing และ WebSockets ดังนั้นจึงมีการซ้อนทับกันบ้าง แต่ WebSockets มีโปรโตคอลที่ได้รับการยอมรับเป็นอย่างดีเฟรมเวิร์ก / API จำนวนมากและค่าใช้จ่ายส่วนหัวที่น้อยลง นี่คือบทความที่ดีเกี่ยวกับหัวข้อ


2

จะมีการนำ WebSocket ไปใช้ใน HTTP / 2 https://tools.ietf.org/html/rfc8441


ไม่มีจะไม่มี ... การเชื่อมต่อ WebSocket จะเจาะผ่าน HTTP / 2 แต่ HTTP / 2 จะไม่แทนที่โปรโตคอลหรือจะกลายเป็นล้าสมัย
Myst

@Myst ฉันไม่ได้พูดอย่างนั้น?
Dzintars

2
ไม่คุณไม่ได้พูดอย่างนั้น คุณเขียนว่าจะมีการติดตั้ง WebSocket ใน HTTP / 2 ซึ่ง IMHO ดูเหมือนสั้นเกินไปและทำให้เข้าใจผิดเนื่องจากมีการละเว้นรายละเอียดที่สำคัญ
Myst

2

ในช่วงเดือนเมษายน 2020 HTTP / 2 ไม่ได้ทำให้ WebSockets ล้าสมัย ข้อได้เปรียบที่ยิ่งใหญ่ที่สุดของ WebSockets ผ่าน HTTP2 คือ

HTTP/2 works only on Browser Level not Application Level

หมายความว่า HTTP / 2 ไม่มี JS API ใด ๆ เช่น WebSockets เพื่ออนุญาตการสื่อสารและถ่ายโอน JSON หรือข้อมูลอื่น ๆ บางประเภทไปยังเซิร์ฟเวอร์โดยตรงจากแอปพลิเคชัน (เช่นเว็บไซต์) ดังนั้นเท่าที่ฉันเชื่อ HTTP / 2 จะทำให้ WebSockets ล้าสมัยหากเริ่มเสนอ API เช่น WebSockets เพื่อพูดคุยกับเซิร์ฟเวอร์ จนกระทั่งมันเพิ่งได้รับการอัพเดตและเร็วกว่ารุ่น HTTP 1.1


2

ณ วันนี้ไม่มี

HTTP / 2 เมื่อเทียบกับ HTTP ช่วยให้คุณรักษาการเชื่อมต่อกับเซิร์ฟเวอร์ จากตรงนั้นคุณสามารถมีสตรีมข้อมูลหลายรายการพร้อมกัน จุดประสงค์คือคุณสามารถผลักดันหลาย ๆ อย่างได้ในเวลาเดียวกันแม้ว่าจะไม่มีลูกค้าร้องขอก็ตาม ตัวอย่างเช่นเมื่อเบราว์เซอร์ขอindex.htmlเซิร์ฟเวอร์อาจต้องการที่จะผลักดันและindex.css index.jsเบราว์เซอร์ไม่ได้ร้องขอ แต่เซิร์ฟเวอร์อาจจัดเตรียมไว้โดยไม่ถูกถามเพราะสามารถสันนิษฐานได้ว่าคุณต้องการภายในไม่กี่วินาที

นี้จะเร็วกว่า HTTP / 1 ทางเลือกของการindex.htmlแยกมันก็ต้องค้นพบindex.jsและindex.cssและแล้วการสร้าง 2 คำขออื่น ๆ สำหรับไฟล์เหล่านั้น HTTP / 2 ช่วยให้เซิร์ฟเวอร์ส่งข้อมูลที่ลูกค้าไม่ได้ถาม

ในบริบทนั้นคล้ายกับ WebSocket แต่ไม่ใช่การออกแบบจริงๆ WebSocket ควรจะอนุญาตให้มีการสื่อสารแบบสองทิศทางคล้ายกับการเชื่อมต่อ TCP หรือการเชื่อมต่อแบบอนุกรม มันเป็นซ็อกเก็ตที่สื่อสารกันได้ นอกจากนี้ความแตกต่างที่สำคัญคือคุณสามารถส่งแพ็กเก็ตข้อมูลใด ๆ ในหน่วยไบต์ดิบโดยไม่ห่อหุ้มในโปรโตคอล HTTP แนวคิดของส่วนหัว, เส้นทาง, สตริงการสืบค้นจะเกิดขึ้นเฉพาะในระหว่างการจับมือกัน แต่ WebSocket จะเปิดกระแสข้อมูล

ความแตกต่างอีกอย่างคือคุณได้รับการเข้าถึง WebSocket ใน Javascript อย่างละเอียดยิ่งขึ้นส่วนเบราว์เซอร์นั้นจัดการกับ HTTP ทั้งหมดที่คุณได้รับกับ HTTP คือสิ่งที่คุณสามารถใส่ใน/XHR fetch()นั่นยังหมายถึงเบราว์เซอร์จะได้รับการตัดและปรับเปลี่ยนส่วนหัว HTTP โดยที่คุณไม่สามารถที่จะควบคุมมัน (เช่นOrigin, Cookiesฯลฯ ) นอกจากนี้ HTTP / 2 ที่สามารถส่งให้กับเบราว์เซอร์คืออะไร นั่นหมายถึง JS ไม่เคยรู้ว่ามีสิ่งใดผลักอยู่เสมอ อีกครั้งเหมาะสมindex.cssและindex.jsเนื่องจากเบราว์เซอร์จะแคช แต่ไม่มากสำหรับแพ็กเก็ตข้อมูล

มันคือทั้งหมดที่อยู่ในชื่อ HTTP ย่อมาจาก HyperText Transfer Protocol เรามุ่งเน้นแนวคิดการโอนสินทรัพย์ WebSocket เป็นเรื่องเกี่ยวกับการสร้างการเชื่อมต่อซ็อกเก็ตที่ข้อมูลไบนารีได้รับการส่งผ่านแบบสองทิศทาง


สิ่งที่เราไม่ได้พูดถึงก็คือ SSE (เหตุการณ์ที่เซิร์ฟเวอร์ส่ง) การพุชข้อมูลไปยังแอปพลิเคชัน (JS) ไม่ใช่ความตั้งใจของ HTTP / 2 แต่เป็นข้อมูลสำหรับ SSE SSE แข็งแกร่งขึ้นด้วย HTTP / 2 แต่มันไม่ใช่การแทนที่ที่แท้จริงสำหรับ WebSockets เมื่อสิ่งที่สำคัญคือตัวข้อมูลเองไม่ใช่ถึงจุดสิ้นสุดของตัวแปร สำหรับแต่ละจุดปลายด้วย WebSocket กระแสข้อมูลใหม่จะถูกสร้างขึ้น แต่ด้วย SSE มันถูกแชร์ระหว่างเซสชัน HTTP / 2 ที่มีอยู่แล้ว


สรุปที่นี่มีวัตถุประสงค์สำหรับแต่ละ:

  • HTTP - ตอบกลับคำขอด้วยเนื้อหาเดียว
  • HTTP / 2 - ตอบกลับคำขอที่มีหลายเนื้อหา
  • SSE - ตอบกลับด้วยสตรีมเหตุการณ์ข้อความทิศทางเดียว (UTF-8)
  • WebSocket - สร้างกระแสข้อมูลไบนารีแบบสองทิศทาง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.