परिचय: Go पर सरल WebSocket से परे
Go पर WebSocket के बुनियादी उदाहरण आमतौर पर एक सरल इको कनेक्शन दिखाते हैं। वास्तविक प्रोडक्शन प्रोजेक्ट्स में - स्टॉक एक्सचेंज टर्मिनलों से लेकर मल्टीप्लेयर गेम और अलर्ट सिस्टम तक - बहुत कुछ आवश्यक है: कक्ष प्रबंधन, Graceful Shutdown, स्केलिंग और सही त्रुटि प्रबंधन। इस लेख में, हम gorilla/websocket लाइब्रेरी का उपयोग करके Go पर real-time एप्लिकेशन बनाने के उन्नत पैटर्न का विश्लेषण करेंगे।
हम Hub (केंद्रीय डिस्पैचर) और Client (व्यक्तिगत कनेक्शन) पर आधारित एक आर्किटेक्चर बनाएंगे, कक्षों के लिए समर्थन जोड़ेंगे, एक दोष-सहिष्णुता तंत्र शामिल करेंगे, और दिखाएंगे कि सर्वर को सही तरीके से कैसे बंद किया जाए।
Hub और Client आर्किटेक्चर: real-time सर्वर का आधार
Hub क्यों?
प्रत्येक WebSocket क्लाइंट एक अलग गोरूटीन है। उन्हें सीधे HTTP हैंडलर से प्रबंधित करना खतरनाक है: इससे डेटा रेस और मेमोरी लीक होती है। Hub पैटर्न पंजीकरण, हटाने और संदेश प्रसारण के लिए एक एकल चैनल के रूप में कार्य करके समस्या का समाधान करता है।
Hub का कार्यान्वयन
package main
import ( "log" "sync")
type Client struct { hub *Hub send chan []byte room string}
type Hub struct { clients map[*Client]bool broadcast chan Message register chan *Client unregister chan *Client mu sync.RWMutex}
type Message struct { Room string Data []byte Sender *Client}
func NewHub() *Hub { return &Hub{ clients: make(map[*Client]bool), broadcast: make(chan Message, 256), register: make(chan *Client), unregister: make(chan *Client), }}
func (h *Hub) Run() { for { select { case client := <-h.register: h.mu.Lock() h.clients[client] = true h.mu.Unlock() log.Printf("क्लाइंट कनेक्ट हुआ। कुल: %d", len(h.clients))
case client := <-h.unregister: h.mu.Lock() if _, ok := h.clients[client]; ok { delete(h.clients, client) close(client.send) } h.mu.Unlock()
case message := <-h.broadcast: h.mu.RLock() for client := range h.clients { // केवल सही कक्ष में भेजें if client.room == message.Room || message.Room == "" { select { case client.send <- message.Data: default: // यदि चैनल भरा हुआ है - क्लाइंट को डिस्कनेक्ट करें h.mu.RUnlock() h.unregister <- client h.mu.RLock() } } } h.mu.RUnlock() } }}मुख्य बिंदु:
- चैनल - register, unregister, broadcast - गोरूटीन को सुरक्षित रूप से सिंक्रोनाइज़ करते हैं।
- RWMutex - क्लाइंट सूची को एक साथ पढ़ने की अनुमति देता है, लेकिन लिखने को ब्लॉक करता है।
- Room-based routing - संदेश केवल उसी कक्ष के क्लाइंट को भेजा जाता है।
कक्ष और सब्सक्रिप्शन प्रबंधन
कक्ष (Rooms) क्लाइंट के तार्किक समूह हैं। उदाहरण के लिए, चैट में प्रत्येक वार्तालाप का अपना कक्ष होता है। हमारे Hub में, कक्ष Client के room फ़ील्ड द्वारा निर्धारित किया जाता है। आइए देखें कि क्लाइंट किसी कक्ष की सदस्यता कैसे लेता है।
WebSocket Upgrade के साथ HTTP हैंडलर
import ( "net/http" "github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true // प्रोडक्शन के लिए origin जाँच से बदलें },}
func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err !=