วงจรชีวิตของ Connection
จนถึงตอนนี้เราปฏิบัติต่อ WebSocket ราวกับว่า มีอยู่ เฉย ๆ คุณเปิด คุณส่ง คุณรับ แต่ connection จริง ๆ ไม่ได้เรียบร้อยขนาดนั้น connection ถือกำเนิด มีชีวิตอยู่ระยะหนึ่ง บางครั้งก็ตายไปโดยไม่เตือนล่วงหน้า และ — ถ้าแอปของคุณดีพอ — ก็ฟื้นคืนชีพกลับมาเอง โมดูลนี้ว่าด้วยวงจรชีวิตทั้งหมดนั้น และหน้านี้คือแผนที่
Connection มีชีวิต
หัวข้อที่มีชื่อว่า “Connection มีชีวิต”ลองคิดถึง connection หนึ่งตัวเหมือนตัวละครที่มีเรื่องราว:
- Connecting — handshake กำลังดำเนินอยู่ ยังส่งอะไรไม่ได้
- Live — socket เปิดอยู่ ข้อความไหลไปมาทั้งสองทิศทาง นี่คือสถานะที่มีความสุข และโค้ดส่วนใหญ่ของคุณก็สมมติว่าคุณอยู่ในสถานะนี้
- Dropped — เน็ตเวิร์กกะพริบหายไปแวบหนึ่ง proxy timeout หรือ server รีสตาร์ต connection ตายไปแล้ว แต่ — และนี่คือกับดัก — codeของคุณอาจยังไม่ได้รับแจ้ง
- Reconnecting — เมื่อตัดสินใจแล้วว่า connection หายไป client จะรอสักครู่แล้วลองใหม่ จากนั้นรอนานขึ้น แล้วก็นานขึ้นอีก จนกว่าจะสำเร็จหรือยอมแพ้
- Closed — การปิดอย่างตั้งใจและสะอาดหมดจด ฝ่ายหนึ่งบอกลา อีกฝ่ายตอบรับ แล้วสายก็ถูกปลดระวางอย่างจงใจ
แนวคิดที่สำคัญที่สุดในโมดูลนี้คือความแตกต่างระหว่าง dropped และ closed connection ที่ closed จบลงเพราะมีคนตั้งใจให้จบ ส่วน connection ที่ dropped จบลงโดยอุบัติเหตุ — และการตรวจจับอุบัติเหตุนั้นอย่างน่าเชื่อถือกลับยากอย่างน่าประหลาดใจ เพราะ connection ที่พังสามารถดูเหมือน connection ที่เงียบสงบและแข็งแรงได้เป๊ะ ๆ
วงจรชีวิตในรูปแบบ state machine
หัวข้อที่มีชื่อว่า “วงจรชีวิตในรูปแบบ state machine”stateDiagram-v2 [*] --> Connecting Connecting --> Live: handshake ok Connecting --> Reconnecting: handshake failed Live --> Dropped: heartbeat missed / network lost Live --> Closed: clean close (1000) Dropped --> Reconnecting: schedule retry Reconnecting --> Connecting: backoff elapsed Reconnecting --> Closed: gave up Closed --> [*]
อ่านไดอะแกรมนี้เหมือนคำสัญญาเกี่ยวกับcodeของคุณ: ทุกลูกศรคือสิ่งที่คุณต้องจัดการ ลูกศร Live to Dropped คือลูกศรที่แอปส่วนใหญ่ลืม เพราะ WebSocket ของเบราว์เซอร์จะไม่ยิง onclose ทันทีเสมอไปเมื่อเน็ตเวิร์กตาย — ซึ่งนั่นคือเหตุผลที่บทเรียนถัดไปมีอยู่
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”โมดูลนี้ — Connection Lifecycle — เปลี่ยนแต่ละลูกศรข้างบนให้กลายเป็นcodeที่ใช้งานได้จริง:
- Connection lifecycle (คุณอยู่ที่นี่) — วงจรชีวิตทั้งหมดในรูปแบบ state machine เดียว
- Heartbeats — ทำไม dead connection ถึงดูเหมือนยังมีชีวิต และ ping/pong พิสูจน์การหายใจได้อย่างไร
- Detecting dead connections — เปลี่ยน heartbeat ที่หายไปให้กลายเป็นความมั่นใจว่า “อันนี้ไปแล้ว ปิดทิ้งเลย”
- Reconnection and backoff — กลับมาอัตโนมัติโดยไม่กระหน่ำ server ที่กำลังดิ้นรน
- Close codes and resume — close handshake ที่สะอาด ความหมายของ code ตัวเลขต่าง ๆ และการเล่นซ้ำ state ที่คุณพลาดไป
เมื่อจบโมดูล คุณจะได้ connection ที่รักษาตัวเองได้: รู้ตัวว่าตายไปแล้ว backoff อย่างสุภาพ reconnect แล้วตามเก็บทุกอย่างที่พลาดไประหว่างที่หายไป
ดูวงจรชีวิตทั้งหมดสักครั้ง
หัวข้อที่มีชื่อว่า “ดูวงจรชีวิตทั้งหมดสักครั้ง”ก่อนจะผ่าทีละขั้น ลองดู connection ตัวหนึ่งใช้ชีวิตครบทั้งวงจรในการรันครั้งเดียว เดโมด้านล่างใช้ socket ในหน้าที่มี WebSocket API จริง — onopen/onmessage/onclose เดียวกัน — ที่เปิดขึ้น รันสักครู่ ถูก drop และถูก reconnect แล้วในที่สุดก็ถูก close อย่างตั้งใจ ดู console บรรยายแต่ละสถานะ
คุณควรจะเห็น: connecting, live, dropped (code 1006 ซึ่งคือการจบแบบผิดปกติ) จากนั้น connecting อีกครั้ง live อีกครั้ง และสุดท้าย close อย่างสะอาดด้วย code 1000 การรันครั้งเดียวนั้นคือโมดูลทั้งหมดนี้ในเวอร์ชันย่อ — ทุกบทเรียนต่อจากนี้จะซูมเข้าไปยังหนึ่งใน transition เหล่านั้น