Skip to content

การเชื่อมต่อซ้ำหลังหลุด (Reconnection Strategy) ​

ในโลกความเป็นจริง เครือข่ายไม่ได้เสถียรเสมอไป ผู้ใช้งานอาจจะเดินเข้าลิฟต์ เปลี่ยนเสาสัญญาณ หรือปิดจอสมาร์ทโฟน ซึ่งล้วนทำให้การเชื่อมต่อ WebSocket ดับวูบ (Disconnect)

นี่คือคำแนะนำแนวทางการเขียนหน้าบ้าน (Frontend Client) เพื่อรับมือปัญหาหลุดบ่อย (Flaky Network) ได้อย่างไร้รอยต่อ

1. การดักจับเหตุการณ์การหลุด ​

สัญญาณการหลุดจะเกิดขึ้นใน Event Listener ws.onclose หรือ ws.onerror ของ WebSocket Object เสมอ

javascript
ws.onclose = (event) => {
    // โค้ดที่ RawPush แจ้งสถานะการปิดจะอยู่ที่ event.code
    console.log("Disconnected! Code:", event.code);
    console.log("Reason:", event.reason);
    
    // ดูว่าเป็นความตั้งใจหลุดหรือไม่
    if (!event.wasClean) {
        console.log("เน็ตหลุดกะทันหัน! ควรพยายามต่อใหม่");
    }
};

ตัวอย่างรหัสบอกสาเหตุ (Close Codes)

  • 1000: ปิดด้วยดี (คุณสั่งปิดแบบ Normal Closure ย้ายหน้าเว็บ)
  • 1006: ปิดโดยผิดปกติกะทันหัน (เน็ตหลุด / สัญญาณตาย) <-- อาการนี้ควรช่วยต่อใหม่!
  • 4001: Server สั่ง close (Token ผิด / Auth Timeout) <-- อาการนี้ ไม่ควร ต่อใหม่จนกว่าจะขอ Token ใหม่จาก Backend

2. วิธีการทำ Exponential Backoff ​

นักพัฒนา ไม่ควรสั่ง connect() ถี่ๆ รัวๆ ทันทีที่เน็ตหลุด เพราะจะเสี่ยงทำให้ฝั่ง Client หน้าเว็บแฮงค์ค้าง และทำให้ Server กลายเป็นโดนยิงถล่ม (DDoS)

แนวปฎิบัติมาตรฐาน: การเวียนตั้งเวลาให้พยายามค่อยๆ ต่อใหม่ (Retry) ทิ้งช่วงห่างขึ้นเรื่อยๆ เรียกว่า Exponential Backoff (2วิ... 4วิ... 8วิ... หลุด)

นี่คือโค้ดตัวอย่างเพื่อให้เชื่อมต่อ RawPush อัตโนมัติ:

javascript
let ws;
const publicKey = "pk_yourproject...";
let authData = null; // เก็บค่า { token, signature } จาก Backend

let reconnectAttempts = 0;
const maxAttempts = 10;

function connect() {
  ws = new WebSocket(`wss://api.rawpush.com/ws?app_key=${publicKey}`);

  ws.onopen = () => {
    // ล้างตัวนับใหม่เมื่อต่อสำเร็จ
    reconnectAttempts = 0;
    
    // Auth อีกครั้งหลังหลุด
    ws.send(JSON.stringify({
      cmd: "auth",
      token: authData.token,
      signature: authData.signature
    }));
  };

  ws.onmessage = (event) => {
      //... รับข้อมูล
  };

  ws.onclose = (e) => {
      // ถ้าโดน block หรือ Token ผิด (Code 4xxx) ไม่ต้องพยายามต่อใหม่
      if (e.code >= 4000) return; 

      if (reconnectAttempts < maxAttempts) {
          // หน่วงเวลาช้าลง 2 เท่า ทุกครั้ง (เริ่มต้นที่ 1000 มิลลิวินาที)
          const timeout = Math.pow(2, reconnectAttempts) * 1000;
          reconnectAttempts++;
          
          console.log(`พยายามเชื่อมต่อใหม่รอบที่ ${reconnectAttempts} ในอีก ${timeout/1000} วินาที...`);
          
          setTimeout(() => connect(), timeout);
      } else {
          console.error("เชื่อมต่อใหม่ไม่สำเร็จ (ยอมแพ้)");
      }
  };
}

// เรียกให้ทำงานครั้งแรก
connect();

3. สิ่งที่ควรทำหลังการเชื่อมต่อซ้ำ ​

เคล็ดลับสำคัญ! ระบบของ RawPush เป็นแบบส่ง-รับ ณ วินาทีนั้น ๆ หากเน็ตของคุณหลุดไป 5 นาที... พอพยายามต่อกลับมาติดใหม่ แล้วรันบรรทัดคำสั่ง auth กับ subscribe กลับคืนเข้ามา ข้อความที่ส่งช่วงที่คุณเน็ตหลุดไป 5 วินาทีนั้นสูญหายถาวร (Fire and Forget) จะไม่ได้ถูกส่งย้อนหลังกลับมาให้

หากแอปพลิเคชันของคุณคือ "ระบบ Real-time สำคัญ" (เช่น จอเทรดหุ้น แดชบอร์ดมอนิเตอร์สถานะ หรือแชท) สิ่งที่ Client (ฝั่ง Frontend) ต้องทำหลังจาก onopen ต่อติดใหม่คือ:

  1. รีบเรียก REST API ดึงข้อมูลย้อนหลัง (Database) เพื่อเช็คว่ามี data อะไรมาใหม่บ้างตอนที่เน็ตหลุด (Fetch History API ของ Backend คุณเอง)
  2. วาดข้อมูลอดีตลงหน้าจอ
  3. พอวาดเสร็จ ก็เริ่มรับ Event จาก RawPush WebSocket ตามปกติ

แค่นี้ก็จะได้ประสบการณ์ Real-time แบบข้ามช่วงเน็ตหลุดได้อย่างไร้รอยต่อแล้ว!

Released under the MIT License.