[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-th-1-1-all-go-websocket-cluster-all--*":3,"academy-blog-translations-h04dj8i9c0xasgf":164},{"data":4,"page":152,"perPage":152,"totalItems":152,"totalPages":152},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_path":11,"created":12,"created_by":13,"expand":14,"id":158,"keywords":159,"locale":134,"published_at":160,"scheduled_at":13,"school_blog":156,"short_description":161,"slug":162,"status":154,"title":6,"updated":163,"updated_by":13,"views":157},"Ep.27 Go กับ WebSocket Cluster - เพิ่มพลังการรองรับผู้ใช้แบบกระจายตัว!","sclblg987654321","school_blog_translations","\u003Cp class=\"p1\">\u003Cstrong>Go กับ WebSocket Cluster - เพิ่มพลังการรองรับผู้ใช้แบบกระจายตัว!\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">ใน EP นี้ เราจะพูดถึงการสร้าง WebSocket Server ที่สามารถทำงานในรูปแบบ Cluster เพื่อรองรับการใช้งานแบบกระจายตัว เพิ่มความสามารถในการรองรับผู้ใช้งานจำนวนมาก และช่วยเพิ่มความเสถียรของระบบครับ!\u003C\u002Fp>\u003Cp class=\"p3\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>Cluster คืออะไร?\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">Cluster คือการรวมเซิร์ฟเวอร์หลายตัวให้ทำงานร่วมกันเสมือนเป็นระบบเดียว โดยมี Load Balancer คอยกระจายงาน (เช่น การเชื่อมต่อ WebSocket) ไปยังเซิร์ฟเวอร์แต่ละตัวใน Cluster\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>ข้อดีของการทำงานแบบ Cluster :\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">1. รองรับผู้ใช้จำนวนมาก : กระจายการเชื่อมต่อไปยังเซิร์ฟเวอร์หลายตัว\u003C\u002Fp>\u003Cp class=\"p3\">2. เพิ่มความเสถียร : หากเซิร์ฟเวอร์บางตัวล่ม ระบบยังคงทำงานได้\u003C\u002Fp>\u003Cp class=\"p3\">3. ปรับขนาดได้ง่าย : เพิ่มหรือลดจำนวนเซิร์ฟเวอร์ตามความต้องการ\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>การจัดการ WebSocket แบบ Cluster\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">ปัญหาหลักที่ต้องแก้ไขใน Cluster\u003C\u002Fp>\u003Cp class=\"p3\">1. Session Stickiness : ทำให้การเชื่อมต่อของผู้ใช้เดิมส่งไปยังเซิร์ฟเวอร์ตัวเดิม\u003C\u002Fp>\u003Cp class=\"p3\">2. การกระจายข้อความ (Message Broadcasting) : ให้ข้อความที่ส่งจากเซิร์ฟเวอร์หนึ่งกระจายไปยังผู้ใช้ทุกคนใน Cluster\u003C\u002Fp>\u003Cp class=\"p3\">3. การซิงโครไนซ์สถานะ (State Synchronization) : รักษาสถานะของผู้ใช้ในเซิร์ฟเวอร์หลายตัว\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>การสร้าง WebSocket Cluster ด้วย Redis Pub\u002FSub\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">Redis Pub\u002FSub ช่วยให้เซิร์ฟเวอร์หลายตัวสามารถสื่อสารกันได้ โดยเซิร์ฟเวอร์ทุกตัวจะ Subscribe (ติดตาม) ข้อความจากช่องเดียวกัน (Channel)\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>ตัวอย่างการใช้ Redis Pub\u002FSub สำหรับ WebSocket Cluster\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">1.&nbsp;ติดตั้ง Redis และ Go Redis Library\u003C\u002Fp>\u003Cp class=\"p3\">ติดตั้ง Redis บนเซิร์ฟเวอร์ของคุณ\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext\">sudo apt install redis\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>เพิ่มไลบรารี Go Redis:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext\">go get github.com\u002Fredis\u002Fgo-redis\u002Fv9\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">2. ตัวอย่างโค้ด WebSocket Cluster\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-plaintext\">package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"net\u002Fhttp\"\n\n    \"github.com\u002Fgorilla\u002Fwebsocket\"\n    \"github.com\u002Fredis\u002Fgo-redis\u002Fv9\"\n)\n\nvar (\n    upgrader = websocket.Upgrader{\n        CheckOrigin: func(r *http.Request) bool {\n            return true\n        },\n    }\n    clients  = make(map[*websocket.Conn]bool)\n    broadcast = make(chan []byte)\n    rdb      = redis.NewClient(&amp;redis.Options{\n        Addr: \"localhost:6379\",\n    })\n    ctx = context.Background()\n)\n\nfunc handleConnections(w http.ResponseWriter, r *http.Request) {\n    conn, err := upgrader.Upgrade(w, r, nil)\n    if err != nil {\n        log.Println(\"Error upgrading connection:\", err)\n        return\n    }\n    defer conn.Close()\n\n    clients[conn] = true\n    defer delete(clients, conn)\n\n    for {\n        _, msg, err := conn.ReadMessage()\n        if err != nil {\n            log.Println(\"Error reading message:\", err)\n            break\n        }\n\n        \u002F\u002F ส่งข้อความไปยัง Redis Channel\n        if err := rdb.Publish(ctx, \"websocketChannel\", msg).Err(); err != nil {\n            log.Println(\"Error publishing to Redis:\", err)\n        }\n    }\n}\n\nfunc handleRedisMessages() {\n    sub := rdb.Subscribe(ctx, \"websocketChannel\")\n    ch := sub.Channel()\n\n    for msg := range ch {\n        log.Printf(\"Received message from Redis: %s\", msg.Payload)\n        broadcast &lt;- []byte(msg.Payload)\n    }\n}\n\nfunc handleBroadcasts() {\n    for {\n        msg := &lt;-broadcast\n        for client := range clients {\n            if err := client.WriteMessage(websocket.TextMessage, msg); err != nil {\n                log.Println(\"Error writing message:\", err)\n                client.Close()\n                delete(clients, client)\n            }\n        }\n    }\n}\n\nfunc main() {\n    http.HandleFunc(\"\u002Fws\", handleConnections)\n\n    go handleBroadcasts()\n    go handleRedisMessages()\n\n    log.Println(\"WebSocket server started at :8080\")\n    log.Fatal(http.ListenAndServe(\":8080\", nil))\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>อธิบายโค้ด\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">1. เชื่อมต่อ Redis : เซิร์ฟเวอร์ทุกตัว Subscribe ไปยัง websocketChannel\u003C\u002Fp>\u003Cp class=\"p3\">2. ส่งข้อความไปยัง Redis : เมื่อมีผู้ใช้ส่งข้อความ ข้อความจะถูก Publish ไปยัง Redis\u003C\u002Fp>\u003Cp class=\"p3\">3. กระจายข้อความจาก Redis : ข้อความที่ได้รับจาก Redis จะถูกส่งไปยังผู้ใช้ทุกคนที่เชื่อมต่อกับเซิร์ฟเวอร์\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>การทดสอบระบบ Cluster\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">1. รัน WebSocket Server หลายตัว (พอร์ตต่างกัน เช่น :8080, :8081)\u003C\u002Fp>\u003Cp class=\"p3\">2. ใช้ NGINX หรือ Load Balancer กระจายคำขอไปยังเซิร์ฟเวอร์แต่ละตัว\u003C\u002Fp>\u003Cp class=\"p3\">3. เชื่อมต่อไคลเอนต์หลายตัว และส่งข้อความเพื่อดูผลลัพธ์\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>ปรับปรุงเพิ่มเติม\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp class=\"p3\">1. เพิ่ม Sticky Sessions : ใช้ Load Balancer เช่น NGINX เพื่อติดตามเซสชันผู้ใช้\u003C\u002Fp>\u003Cp class=\"p3\">2. Monitor Redis : ใช้เครื่องมือเช่น RedisInsight เพื่อตรวจสอบข้อความและช่อง Redis\u003C\u002Fp>\u003Cp class=\"p3\">3. รองรับการ Scaling อัตโนมัติ : ใช้ Kubernetes สำหรับจัดการจำนวนเซิร์ฟเวอร์\u003C\u002Fp>\u003Cp class=\"p4\">&nbsp;\u003C\u002Fp>\u003Cp class=\"p3\">\u003Cstrong>สรุปง่ายๆ\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul class=\"ul1\">\u003Cli class=\"li3\">ใช้ Redis Pub\u002FSub สำหรับการกระจายข้อความใน WebSocket Cluster\u003C\u002Fli>\u003Cli class=\"li3\">ใช้ NGINX หรือ Load Balancer เพื่อกระจายการเชื่อมต่อ\u003C\u002Fli>\u003Cli class=\"li5\">ปรับปรุงการซิงโครไนซ์สถานะและเพิ่ม\u003Cspan class=\"s2\"> Sticky Sessions \u003C\u002Fspan>เพื่อเพิ่มประสิทธิภาพ\u003C\u002Fli>\u003C\u002Ful>","23_11zon_k6sut4x0oi.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fb5wlxq7hllxi2qg\u002F23_11zon_k6sut4x0oi.webp","2026-03-04 08:34:15.693Z","",{"keywords":15,"locale":128,"school_blog":138},[16,23,28,33,38,43,48,53,58,63,68,73,78,83,88,93,98,103,108,113,118,123],{"collectionId":17,"collectionName":18,"created":19,"created_by":13,"id":20,"name":21,"updated":22,"updated_by":13},"sclkey987654321","school_keywords","2026-03-04 08:20:11.547Z","ey3puyme01a9bsw","Go","2026-04-10 16:07:25.893Z",{"collectionId":17,"collectionName":18,"created":24,"created_by":13,"id":25,"name":26,"updated":27,"updated_by":13},"2026-03-04 08:20:14.253Z","ah6lvy4x8qe08l5","Golang","2026-04-10 16:07:26.172Z",{"collectionId":17,"collectionName":18,"created":29,"created_by":13,"id":30,"name":31,"updated":32,"updated_by":13},"2026-03-04 08:33:59.518Z","7pqn3y8ffwzzde5","ภาษา Go","2026-04-10 16:08:04.777Z",{"collectionId":17,"collectionName":18,"created":34,"created_by":13,"id":35,"name":36,"updated":37,"updated_by":13},"2026-03-04 08:34:05.004Z","q6s3j8b957nwa9d","การพัฒนา Go","2026-04-10 16:08:06.721Z",{"collectionId":17,"collectionName":18,"created":39,"created_by":13,"id":40,"name":41,"updated":42,"updated_by":13},"2026-03-04 08:34:00.920Z","ecac9y661or1xka","WebSocket","2026-04-10 16:08:05.227Z",{"collectionId":17,"collectionName":18,"created":44,"created_by":13,"id":45,"name":46,"updated":47,"updated_by":13},"2026-03-04 08:34:07.677Z","6sjd7h1ggczn786","Cluster","2026-04-10 16:08:07.645Z",{"collectionId":17,"collectionName":18,"created":49,"created_by":13,"id":50,"name":51,"updated":52,"updated_by":13},"2026-03-04 08:34:10.254Z","rss87kgvhtvkri1","Redis Pub\u002FSub","2026-04-10 16:08:08.714Z",{"collectionId":17,"collectionName":18,"created":54,"created_by":13,"id":55,"name":56,"updated":57,"updated_by":13},"2026-03-04 08:34:11.913Z","5r1cyrfomvaxrha","รองรับผู้ใช้","2026-04-10 16:08:09.283Z",{"collectionId":17,"collectionName":18,"created":59,"created_by":13,"id":60,"name":61,"updated":62,"updated_by":13},"2026-03-04 08:34:12.496Z","992k3hc4xxojtaj","ความเสถียร","2026-04-10 16:08:09.493Z",{"collectionId":17,"collectionName":18,"created":64,"created_by":13,"id":65,"name":66,"updated":67,"updated_by":13},"2026-03-04 08:34:13.538Z","7wsdz75zmgcp4c3","การกระจายข้อความ","2026-04-10 16:08:09.823Z",{"collectionId":17,"collectionName":18,"created":69,"created_by":13,"id":70,"name":71,"updated":72,"updated_by":13},"2026-03-04 08:34:14.103Z","6js08ebl8udwy5e","การซิงโครไนซ์สถานะ","2026-04-10 16:08:10.006Z",{"collectionId":17,"collectionName":18,"created":74,"created_by":13,"id":75,"name":76,"updated":77,"updated_by":13},"2026-03-04 08:27:15.893Z","keubtbdqa4mblx3","การพัฒนาโปรแกรม","2026-04-10 16:07:38.769Z",{"collectionId":17,"collectionName":18,"created":79,"created_by":13,"id":80,"name":81,"updated":82,"updated_by":13},"2026-03-04 08:32:27.645Z","vfe4f15x4b3afpm","การศึกษาการเขียนโปรแกรม","2026-04-10 16:07:54.538Z",{"collectionId":17,"collectionName":18,"created":84,"created_by":13,"id":85,"name":86,"updated":87,"updated_by":13},"2026-03-04 08:31:30.863Z","oyltq82epf0vqka","การเขียนโปรแกรม","2026-04-10 16:07:41.883Z",{"collectionId":17,"collectionName":18,"created":89,"created_by":13,"id":90,"name":91,"updated":92,"updated_by":13},"2026-03-04 08:34:09.187Z","3zp82zk9hqz13ko","การเขียนโปรแกรม Go","2026-04-10 16:08:08.225Z",{"collectionId":17,"collectionName":18,"created":94,"created_by":13,"id":95,"name":96,"updated":97,"updated_by":13},"2026-03-04 08:32:29.161Z","uewvwdt9cf41o8n","การเขียนโปรแกรมสำหรับมือใหม่","2026-04-10 16:07:54.935Z",{"collectionId":17,"collectionName":18,"created":99,"created_by":13,"id":100,"name":101,"updated":102,"updated_by":13},"2026-03-04 08:32:27.254Z","xl8ixz1jmfnab5f","ฝึกเขียนโปรแกรม","2026-04-10 16:07:54.377Z",{"collectionId":17,"collectionName":18,"created":104,"created_by":13,"id":105,"name":106,"updated":107,"updated_by":13},"2026-03-04 08:32:35.062Z","o0u15pkykswaj0k","พัฒนาโปรแกรม","2026-04-10 16:07:56.758Z",{"collectionId":17,"collectionName":18,"created":109,"created_by":13,"id":110,"name":111,"updated":112,"updated_by":13},"2026-03-04 08:31:53.015Z","801w5t09mfaa9hl","ภาษาโปรแกรม","2026-04-10 16:07:46.625Z",{"collectionId":17,"collectionName":18,"created":114,"created_by":13,"id":115,"name":116,"updated":117,"updated_by":13},"2026-03-04 08:32:24.473Z","xquecx7u5svb567","โปรแกรม","2026-04-10 16:07:53.714Z",{"collectionId":17,"collectionName":18,"created":119,"created_by":13,"id":120,"name":121,"updated":122,"updated_by":13},"2026-03-04 08:26:56.612Z","yf74wkqyamfc5qx","โปรแกรมเมอร์","2026-04-10 16:07:36.426Z",{"collectionId":17,"collectionName":18,"created":124,"created_by":13,"id":125,"name":126,"updated":127,"updated_by":13},"2026-03-04 08:26:59.195Z","gab60xd583s3qaw","Superdev School","2026-04-10 16:07:37.087Z",{"code":129,"collectionId":130,"collectionName":131,"created":132,"flag":133,"id":134,"is_default":135,"label":136,"updated":137},"th","pbc_1989393366","locales","2026-01-22 10:59:55.832Z","twemoji:flag-thailand","s8wri3bt4vgg2ji",true,"Thai","2026-04-10 15:42:46.614Z",{"category":139,"collectionId":140,"collectionName":141,"expand":142,"id":156,"views":157},"wqxt7ag2gn7xcmk","pbc_2105096300","school_blogs",{"category":143},{"blogIds":144,"collectionId":145,"collectionName":146,"created":147,"created_by":13,"id":139,"image":148,"image_alt":13,"image_path":149,"label":150,"name":151,"priority":152,"publish_at":153,"scheduled_at":13,"status":154,"updated":155,"updated_by":13},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:33:53.210Z","59ty92ns80w_15oc1implw.png","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fwqxt7ag2gn7xcmk\u002F59ty92ns80w_15oc1implw.png",{"en":151,"th":151},"Golang The Series",1,"2026-03-16 04:39:38.440Z","published","2026-04-25 02:32:15.470Z","h04dj8i9c0xasgf",437,"b5wlxq7hllxi2qg",[20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125],"2025-01-27 04:41:33.464Z","เรียนรู้วิธีสร้าง WebSocket Server ในรูปแบบ Cluster ด้วย Redis Pub\u002FSub เพื่อรองรับผู้ใช้จำนวนมากและเพิ่มความเสถียรของระบบ","go-websocket-cluster","2026-04-25 02:47:30.426Z",{"th":162}]