[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-th-1-1-all-ep108-timeout-connection-cleanup-websocket-golang-all--*":3,"academy-blog-translations-l3cnyp1es5143k8":89},{"data":4,"page":77,"perPage":77,"totalItems":77,"totalPages":77},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_path":11,"created":12,"created_by":13,"expand":14,"id":83,"keywords":84,"locale":59,"published_at":85,"scheduled_at":13,"school_blog":81,"short_description":86,"slug":87,"status":79,"title":6,"updated":88,"updated_by":13,"views":82},"EP.108 การจัดการ Timeout และ Connection Cleanup แบบ Advanced","sclblg987654321","school_blog_translations","\u003Cp>เมื่อ WebSocket Server ของคุณเข้าสู่ Production Environment จริง ปัญหาที่มักพบคือ connection ที่หลุดค้าง (stale) หรือ idle connection ที่ไม่มีการใช้งาน แต่ยังใช้ทรัพยากรของระบบอยู่\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>หากปล่อยไว้โดยไม่มีการจัดการที่ดี อาจเกิด Resource Leak ซึ่งจะทำให้ CPU, Memory ถูกใช้งานโดยเปล่าประโยชน์ ส่งผลให้ระบบหน่วง ช้า และล่มได้ในที่สุด\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>ใน EP นี้ เราจะเรียนรู้เทคนิคสำคัญในการ:\u003C\u002Fp>\u003Cul>\u003Cli>ตั้งเวลา Timeout เพื่อตรวจจับการเชื่อมต่อที่ไม่ตอบสนอง\u003C\u002Fli>\u003Cli>ตรวจสอบ connection ที่ idle\u003C\u002Fli>\u003Cli>สร้างกลไก Cleanup เพื่อจัดการ stale connection\u003Cbr>ทั้งหมดนี้เพื่อให้ WebSocket Server เสถียร, ปลอดภัย และ รองรับการขยายตัวได้ในระดับ Production 🔧\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🧩 1. ทำไมต้องมี Timeout และ Cleanup?\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>WebSocket เป็นการเชื่อมต่อแบบ long-lived ที่อาจค้างอยู่ได้นานโดยไม่ถูกปิดอย่างถูกต้อง เช่น:\u003C\u002Fp>\u003Cul>\u003Cli>ผู้ใช้ปิด browser ทันทีโดยไม่ส่ง close frame\u003C\u002Fli>\u003Cli>การหลุดของเครือข่าย (Network Drop)\u003C\u002Fli>\u003Cli>Client ไม่ส่งข้อมูลนานเกินไป\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>หากไม่มีระบบจัดการที่ดี จะทำให้เกิด:\u003C\u002Fp>\u003Cul>\u003Cli>❌ Memory Leak จาก connection ค้าง\u003C\u002Fli>\u003Cli>❌ เพิ่มภาระ CPU โดยไม่จำเป็น\u003C\u002Fli>\u003Cli>❌ จำกัดจำนวนผู้ใช้งานที่ระบบสามารถรองรับได้\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🕒 2. เทคนิคการตั้ง Timeout ด้วย Ping\u002FPong\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>Go รองรับ Ping\u002FPong ผ่าน \u003Ccode inline=\"\">gorilla\u002Fwebsocket\u003C\u002Fcode> ซึ่งใช้ในการตรวจสอบว่า client ยัง active อยู่หรือไม่\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>✅ ตัวอย่างโค้ด:\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">const (\n\tpongWait   = 10 * time.Second\n\tpingPeriod = (pongWait * 9) \u002F 10\n)\n\nconn.SetReadDeadline(time.Now().Add(pongWait))\n\nconn.SetPongHandler(func(string) error {\n\tconn.SetReadDeadline(time.Now().Add(pongWait))\n\treturn nil\n})\n\nticker := time.NewTicker(pingPeriod)\ndefer ticker.Stop()\n\nfor {\n\tselect {\n\tcase &lt;-ticker.C:\n\t\tif err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {\n\t\t\tlog.Println(\"Ping error:\", err)\n\t\t\treturn\n\t\t}\n\tdefault:\n\t\t_, _, err := conn.ReadMessage()\n\t\tif err != nil {\n\t\t\tlog.Println(\"Connection closed:\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>🔍 คำอธิบาย:\u003C\u002Fh3>\u003Cul>\u003Cli>\u003Ccode inline=\"\">SetReadDeadline\u003C\u002Fcode>: ตั้ง timeout หากไม่ได้รับข้อมูลหรือ pong\u003C\u002Fli>\u003Cli>\u003Ccode inline=\"\">WriteMessage(PingMessage)\u003C\u002Fcode>: ส่ง Ping ไปหา client\u003C\u002Fli>\u003Cli>\u003Ccode inline=\"\">SetPongHandler\u003C\u002Fcode>: หาก client ตอบกลับ จะต่ออายุ timeout\u003C\u002Fli>\u003Cli>หากหมดเวลา → ตัด connection อัตโนมัติ\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🧹 3. Cleanup Stale Connections ด้วย Worker\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>ในระบบขนาดใหญ่ เราอาจมี connection เป็นหมื่น จำเป็นต้องมี worker ที่คอยล้าง connection ที่ไม่ active ออกจาก memory\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>✅ ตัวอย่างโค้ด:\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-go\">type Client struct {\n\tID         string\n\tConnection *websocket.Conn\n\tLastActive time.Time\n}\n\nfunc cleanupInactiveConnections() {\n\tfor {\n\t\ttime.Sleep(30 * time.Second)\n\t\tfor id, client := range clients {\n\t\t\tif time.Since(client.LastActive) &gt; 1*time.Minute {\n\t\t\t\tlog.Printf(\"Closing inactive connection: %s\\n\", id)\n\t\t\t\tclient.Connection.Close()\n\t\t\t\tdelete(clients, id)\n\t\t\t}\n\t\t}\n\t}\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cul>\u003Cli>ตรวจสอบทุก 30 วิ\u003C\u002Fli>\u003Cli>หาก inactive เกิน 1 นาที → ปิด connection + ลบออก\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>⚙️ 4. Best Practices สำหรับ Timeout และ Cleanup\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cfigure class=\"table\">\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>แนวทาง\u003C\u002Fth>\u003Cth>รายละเอียด\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd>⏱ กำหนด Read\u002FWrite Deadline\u003C\u002Ftd>\u003Ctd>ตัด connection ที่ไม่ตอบสนอง\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>🔄 ใช้ Ping\u002FPong Mechanism\u003C\u002Ftd>\u003Ctd>ตรวจสอบความ active ของ client\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>🧹 ใช้ Goroutine Cleanup Worker\u003C\u002Ftd>\u003Ctd>ลบ connection ที่หมดอายุ\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>🧠 เก็บ Timestamp ของการใช้งานครั้งล่าสุด\u003C\u002Ftd>\u003Ctd>เพื่อใช้ในการตรวจสอบ activity\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>🧯 จัดการ panic\u003C\u002Ftd>\u003Ctd>ป้องกันระบบล่มขณะ cleanup\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Ffigure>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🧠 5. Debug และ Monitor การทำงาน\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>เมื่อติดตั้งระบบ Timeout และ Cleanup แล้ว อย่าลืมใช้:\u003C\u002Fp>\u003Cul>\u003Cli>Log: เพื่อเก็บข้อมูลเวลาตัด connection\u003C\u002Fli>\u003Cli>Metrics: เพื่อตรวจสอบจำนวน active connection\u003C\u002Fli>\u003Cli>pprof: ตรวจสอบว่ามี goroutine หรือ memory leak หรือไม่\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🚀 ท้าให้ลอง!\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>ลองเปิด Ping\u002FPong + Timeout แล้ว:\u003C\u002Fp>\u003Cul>\u003Cli>ทิ้ง connection ไว้แบบ idle\u003C\u002Fli>\u003Cli>ปิด browser โดยไม่ส่ง close\u003C\u002Fli>\u003Cli>ดูว่า server ปิด connection ให้อัตโนมัติหรือไม่\u003C\u002Fli>\u003C\u002Ful>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>คุณจะพบว่า WebSocket Server ของคุณ:\u003C\u002Fp>\u003Cp>✅ เบาลง\u003Cbr>✅ ไม่กิน resource ค้าง\u003Cbr>✅ พร้อมรับ load ได้มากขึ้น 🚀\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Chr>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>🌟 EP ถัดไป:\u003C\u002Fh2>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>EP.109: การปรับปรุง Performance สำหรับ Mobile Devices เรียนรู้เทคนิคทำให้ WebSocket ทำงานบนมือถือได้ดีขึ้น เช่น:\u003C\u002Fp>\u003Cul>\u003Cli>ลดการใช้พลังงาน\u003C\u002Fli>\u003Cli>จัดการการ reconnect เมื่อสัญญาณหาย\u003C\u002Fli>\u003Cli>ปรับ timeout สำหรับผู้ใช้ mobile\u003C\u002Fli>\u003C\u002Ful>\u003Cp>📱 พร้อมตัวอย่างโค้ดจริงสำหรับระบบ Production!\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Cp>\u003Cstrong>อ่านบทความ Series อื่นๆ\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FGolang\">\u003Cstrong>Golang The Series\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FJS2GO\">\u003Cstrong>JS2GO\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FTailwind%20CSS\">\u003Cstrong>10 Ep ที่จะให้คุณเป็นมือโปร Tailwind CSS ในชั่วข้ามคืน\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>🔵 Facebook: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.academy.th\">\u003Cstrong>https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.academy.th\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>🔴 YouTube : \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.youtube.com\u002Fchannel\u002FUC2eI2RxcA2zbTqZyHyWIfRg\">\u003Cstrong>Superdev Academy\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>📸 Instagram: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.instagram.com\u002Fsuperdevschool\u002F\">\u003Cstrong>Superdev Academy\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>🎬 TikTok: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.tiktok.com\u002F@superdevacademy?lang=th-TH\">\u003Cstrong>https:\u002F\u002Fwww.tiktok.com\u002F@superdevacademy?lang=th-TH\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>🌐 Website: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdevacademy.com\u002F\">\u003Cstrong>https:\u002F\u002Fwww.superdevacademy.com\u002F\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>","187_11zon_jcx1669axb.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F29obs9yzyu0qjp5\u002F187_11zon_jcx1669axb.webp","2026-03-04 08:45:36.600Z","",{"keywords":15,"locale":53,"school_blog":63},[16,23,28,33,38,43,48],{"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:44:47.385Z","li4cs2v3atd0wds","Production","2026-04-10 16:12:49.890Z",{"collectionId":17,"collectionName":18,"created":24,"created_by":13,"id":25,"name":26,"updated":27,"updated_by":13},"2026-03-04 08:44:48.724Z","s6xhnfomy7n5ycp","WebSocket Server","2026-04-10 16:12:50.171Z",{"collectionId":17,"collectionName":18,"created":29,"created_by":13,"id":30,"name":31,"updated":32,"updated_by":13},"2026-03-04 08:45:35.697Z","14mxfvvebe39f82","Cleanup","2026-04-10 16:13:00.513Z",{"collectionId":17,"collectionName":18,"created":34,"created_by":13,"id":35,"name":36,"updated":37,"updated_by":13},"2026-03-04 08:45:35.177Z","ljqmsdx1e0bcmav","Timeout","2026-04-10 16:13:00.233Z",{"collectionId":17,"collectionName":18,"created":39,"created_by":13,"id":40,"name":41,"updated":42,"updated_by":13},"2026-03-04 08:20:14.253Z","ah6lvy4x8qe08l5","Golang","2026-04-10 16:07:26.172Z",{"collectionId":17,"collectionName":18,"created":44,"created_by":13,"id":45,"name":46,"updated":47,"updated_by":13},"2026-03-04 08:20:11.547Z","ey3puyme01a9bsw","Go","2026-04-10 16:07:25.893Z",{"collectionId":17,"collectionName":18,"created":49,"created_by":13,"id":50,"name":51,"updated":52,"updated_by":13},"2026-03-04 08:34:00.920Z","ecac9y661or1xka","WebSocket","2026-04-10 16:08:05.227Z",{"code":54,"collectionId":55,"collectionName":56,"created":57,"flag":58,"id":59,"is_default":60,"label":61,"updated":62},"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":64,"collectionId":65,"collectionName":66,"expand":67,"id":81,"views":82},"wqxt7ag2gn7xcmk","pbc_2105096300","school_blogs",{"category":68},{"blogIds":69,"collectionId":70,"collectionName":71,"created":72,"created_by":13,"id":64,"image":73,"image_alt":13,"image_path":74,"label":75,"name":76,"priority":77,"publish_at":78,"scheduled_at":13,"status":79,"updated":80,"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":76,"th":76},"Golang The Series",1,"2026-03-16 04:39:38.440Z","published","2026-04-25 02:32:15.470Z","l3cnyp1es5143k8",221,"29obs9yzyu0qjp5",[20,25,30,35,40,45,50],"2025-11-10 09:04:40.562Z","เรียนรู้วิธีจัดการ WebSocket ที่หลุดหรือค้างด้วยเทคนิค Timeout และ Connection Cleanup เพื่อให้ระบบของคุณทำงานได้เสถียรและประหยัด resource มากที่สุด พร้อมตัวอย่างโค้ด Go ที่ใช้ได้จริงใน Production","ep108-timeout-connection-cleanup-websocket-golang","2026-04-25 02:47:54.914Z",{"th":87}]