การกระจายข้อความ
ส่งไปยังไคลเอนต์หลายราย
การกระจายข้อความ เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
การส่งข้อมูลไปยังไคลเอ็นต์หลายราย
ห้องแชตและฟีดสดจำเป็นต้องส่งข้อความเดียวไปยังไคลเอ็นต์ที่เชื่อมต่ออยู่ทุกตัว เนื่องจาก WebSocket แต่ละรายการมีตัวเขียนได้เพียงหนึ่งตัว คุณจึงต้องใช้รูปแบบการประสานงานที่เรียกว่า ฮับ
รูปแบบฮับ
ฮับคือกอรูทีนกลางที่เป็นเจ้าของชุดไคลเอ็นต์และช่องสัญญาณสำหรับกระจายข้อความ ไคลเอ็นต์จะลงทะเบียน ยกเลิกการลงทะเบียน และฮับจะกระจายข้อความไปยังไคลเอ็นต์เหล่านั้น จะไม่มีการเข้าถึงแมปร่วมโดยตรงจากกอรูทีนหลายตัว
โครงสร้างข้อมูลของฮับ
ฮับเก็บข้อมูลต่อไปนี้:
- ชุดไคลเอ็นต์ (
map[*Client]bool) - ช่องสัญญาณ
broadcastสำหรับข้อความ - ช่องสัญญาณ
registerและunregister
type Hub struct {
clients map[*Client]bool
broadcast chan []byte
register chan *Client
unregister chan *Client
}ลูปการทำงานของฮับ
กอรูทีน Run เพียงตัวเดียวจะเลือกทำงานจากช่องสัญญาณต่าง ๆ เนื่องจากมีเพียงกอรูทีนนี้ที่แก้ไขแมป จึงไม่จำเป็นต้องใช้มิวเท็กซ์
func (h *Hub) Run() {
for {
select {
case c := <-h.register:
h.clients[c] = true
case c := <-h.unregister:
delete(h.clients, c)
close(c.send)
case msg := <-h.broadcast:
for c := range h.clients {
c.send <- msg
}
}
}
}ช่องสัญญาณส่งข้อมูลของแต่ละไคลเอ็นต์
ไคลเอ็นต์แต่ละรายมี send chan []byte ซึ่งเป็นช่องสัญญาณแบบมีบัฟเฟอร์ ฮับจะเขียนข้อมูลลงในช่องนี้ ส่วนกอรูทีนตัวเขียนเฉพาะจะดึงข้อมูลจากช่องแล้วส่งไปยังซ็อกเก็ต วิธีนี้สอดคล้องกับกฎตัวเขียนหนึ่งตัว
type Client struct {
conn *websocket.Conn
send chan []byte
}กอรูทีนตัวเขียน
ไคลเอ็นต์แต่ละรายจะเรียกใช้ writePump ซึ่งวนอ่านค่าจาก send แล้วเขียนลงในซ็อกเก็ต หากช่องสัญญาณถูกปิด มันจะส่งเฟรมปิด
func (c *Client) writePump() {
for msg := range c.send {
c.conn.WriteMessage(websocket.TextMessage, msg)
}
}การหลีกเลี่ยงไคลเอ็นต์ที่ช้า
หากไคลเอ็นต์รายหนึ่งทำงานช้า บัฟเฟอร์ของ send จะเต็ม นโยบายที่ใช้กันทั่วไปคือ หากบัฟเฟอร์เต็ม ให้ยกเลิกไคลเอ็นต์รายนั้นแทนการหยุดรอจนทำให้ฮับทั้งหมดหยุดทำงาน
select {
case c.send <- msg:
default:
close(c.send)
delete(h.clients, c)
}เหตุผลที่ใช้ช่องสัญญาณแทนมิวเท็กซ์
คติของ Go คือ: "แบ่งปันหน่วยความจำด้วยการสื่อสาร" การรวมการแก้ไขทั้งหมดไว้ที่กอรูทีนเดียวผ่านช่องสัญญาณช่วยหลีกเลี่ยงสภาวะแข่งขันบนแมปไคลเอ็นต์โดยไม่ต้องล็อกอย่างชัดเจน
การกระจายข้อความ
ตัวจัดการใด ๆ ก็สามารถกระจายข้อความได้ด้วยการส่งผ่านช่องสัญญาณของฮับ จากนั้นฮับจะกระจายข้อความไปยังไคลเอ็นต์ที่ลงทะเบียนไว้ทุกตัว
hub.broadcast <- []byte("server announcement")การส่งแบบเจาะจงกับการกระจายทั้งหมด
สำหรับห้องแชตหรือข้อความส่วนตัว ให้จัดเก็บไคลเอ็นต์โดยใช้รหัสห้องหรือรหัสผู้ใช้เป็นคีย์ แล้ววนดูเฉพาะกลุ่มย่อยที่เกี่ยวข้องแทนการวนดูไคลเอ็นต์ทั้งหมด วิธีนี้ช่วยให้แชตที่มีหลายห้องยังทำงานได้อย่างมีประสิทธิภาพ
ตัวอย่างที่รันได้: กระจายข้อมูลด้วยช่องสัญญาณ
โปรแกรมนี้ทำงานได้ในตัวและจำลองฮับที่กระจายข้อความหนึ่งข้อความไปยังช่องสัญญาณของไคลเอ็นต์หลายราย โดยใช้เฉพาะไลบรารีมาตรฐานและกอรูทีน
package main
import (
"fmt"
"sync"
)
func main() {
clients := []chan string{make(chan string, 1), make(chan string, 1), make(chan string, 1)}
msg := "hello all"
for _, c := range clients {
c <- msg // fan-out
}
var wg sync.WaitGroup
for i, c := range clients {
wg.Add(1)
go func(id int, ch chan string) {
defer wg.Done()
fmt.Printf("client %d got: %s\n", id, <-ch)
}(i, c)
}
wg.Wait()
}ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจเรื่องการกระจายข้อความ
สรุปทบทวน
คุณได้เรียนรู้การกระจายข้อความไปยังไคลเอ็นต์หลายรายดังนี้:
- กอรูทีนฮับเป็นเจ้าของชุดไคลเอ็นต์และช่องสัญญาณสำหรับกระจายข้อความ
- ไคลเอ็นต์แต่ละรายมีช่องสัญญาณส่งข้อมูลแบบมีบัฟเฟอร์ ซึ่งกอรูทีนตัวเขียนจะดึงข้อมูลออกไป
- วิธีนี้สอดคล้องกับกฎตัวเขียนหนึ่งตัวต่อการเชื่อมต่อหนึ่งรายการ
- ยกเลิกไคลเอ็นต์ที่ช้าเพื่อให้ฮับยังตอบสนองได้
คำถามที่พบบ่อย
บทเรียน “การกระจายข้อความ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การกระจายข้อความ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การกระจายข้อความ”
ส่งไปยังไคลเอนต์หลายราย คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การกระจายข้อความ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐาน WebSocket
- การใช้ gorilla/websocket
- การกระจายข้อความ
- การจัดการการเชื่อมต่อ