SYSTEM ARCHITECTURE PROPOSED CLOSED-SOURCE PROJECT DESIGN WRITEUP / SAMPLE

// Engineering case study — 001

Engineering a Low-Latency
Realtime Synchronization Engine.

เจาะลึกแนวทางออกแบบการส่งข้อมูลแบบ Real-time การจัดการ State และการรักษาความถูกต้องของข้อมูล โดยแยกเส้นทางรับคำสั่งออกจากการแสดงผลอย่างชัดเจน

DATE: ยังไม่ระบุวันเผยแพร่ HARDENING: DESIGN TARGET Node.js / WebSockets / SQLite

00 Project Overview

PROJECT TYPE Realtime State Platform
DESIGN FOCUS Ordering / Consistency / Latency
EVIDENCE STATUS Concept / Pending Validation
เกี่ยวกับเนื้อหานี้: บทความเป็นต้นแบบสำหรับนำไปแทนด้วยรายละเอียดโปรเจกต์จริง สถาปัตยกรรมเป็นข้อเสนอในการออกแบบ ตัวเลข Benchmark ด้านล่างเป็นข้อมูลตัวอย่าง ไม่ใช่ผลวัดหรือหลักฐานการรองรับโหลดของระบบที่พัฒนาแล้ว

เป้าหมายคือออกแบบระบบที่ Client หลายตัวติดตามและเปลี่ยนแปลง State ร่วมกันได้ โดยให้เซิร์ฟเวอร์เป็นผู้ตัดสินสถานะสุดท้าย เหมาะกับ Dashboard, ระบบจำลอง และเครื่องมือจัดการงานร่วมกัน

01 The Challenge & Constraints

การ Polling เป็นระยะอาจสร้าง Request แม้ไม่มีข้อมูลเปลี่ยนแปลง และทำให้ Client ต้องรอรอบถัดไปก่อนเห็นสถานะใหม่ อย่างไรก็ตาม Polling ยังเหมาะกับระบบที่อัปเดตไม่บ่อยและต้องการความเรียบง่าย

โจทย์หลักที่ต้องแก้

  • Update delay: ลดช่วงเวลาระหว่างการเปลี่ยน State และการแสดงผล
  • Concurrent actions: จัดลำดับคำสั่งที่แก้ไข Entity เดียวกัน
  • Reconnect: กู้สถานะเมื่อ Client หลุดการเชื่อมต่อ
  • Limited resources: จำกัด Queue, Payload และจำนวน Connection ตามทรัพยากร

ขอบเขตของแบบออกแบบเริ่มต้น

เริ่มจาก Application Instance เดียว ใช้ Queue ต่อ Entity และฐานข้อมูลแบบ Transaction เมื่อขยายหลาย Instance ต้องมีการกำหนดเจ้าของ State หรือเพิ่มกลไกประสานงานร่วมกัน Queue ในหน่วยความจำของแต่ละ Process เพียงอย่างเดียวไม่เพียงพอ

02 Architecture Topology

แยก Gateway, Validation, State Resolution และ Persistence เพื่อให้ทดสอบแต่ละส่วนได้โดยไม่ผูกกับ UI และลดความซับซ้อนในตัวจัดการ WebSocket

FIG. 01 / PROPOSED AUTHORITATIVE STATE FLOW
+-------------+       +---------------------+
|  Client UI  | <---> |  WebSocket Gateway  |
+-------------+  WSS  +----------+----------+
                                |
                    +-----------v------------+
                    | Auth / Origin / Schema |
                    | Limits / Authorization |
                    +-----------+------------+
                                |
                    +-----------v------------+
                    | Bounded Per-Entity Queue|
                    +-----------+------------+
                                |
                    +-----------v------------+
                    |     State Resolver     |
                    | Version / Idempotency  |
                    +-----------+------------+
                                |
                    +-----------v------------+
                    | Transaction / Database |
                    +-----------+------------+
                                |
                    +-----------v------------+
                    | Commit → ACK / Publish |
                    +-----------+------------+
                                |
                         Authorized Clients

Reconnect → Last Seen Version → Delta or Snapshot
            

ทุก Command ต้องผ่านการตรวจสอบสิทธิ์ และเผยแพร่ State หลังยืนยันการบันทึกสำเร็จ เส้นทาง Reconnect ใช้ Version เพื่อตรวจข้อมูลที่ขาดหาย

เส้นทางการทำงานของหนึ่ง Action

  1. Client ส่ง Command พร้อม requestId และ expectedVersion
  2. Gateway ตรวจ Session, Origin, ขนาด Payload และ Schema
  3. ตรวจสิทธิ์ต่อ Entity และส่งเข้า Queue ที่มีขนาดจำกัด
  4. Resolver ตรวจ Version และกฎของระบบภายในขอบเขต Transaction
  5. บันทึก State พร้อมข้อมูลป้องกันการประมวลผล Command ซ้ำ
  6. หลัง Commit จึงตอบ ACK และส่ง Event ให้ผู้รับที่มีสิทธิ์

เมื่อการเชื่อมต่อขาดหาย

Client ส่ง Version ล่าสุดที่ได้รับเพื่อขอ Delta หากประวัติไม่เพียงพอให้ส่ง Snapshot ใหม่ และต้องรองรับ Event ซ้ำหรือขาดช่วง ไม่ถือว่า WebSocket ทำให้การส่งข้อมูลเป็น Exactly-once โดยอัตโนมัติ

ข้อจำกัดที่ต้องออกแบบเพิ่ม: การ Commit แล้วส่ง Event ทันทีอาจเกิดช่องว่างหาก Process ล่มระหว่างสองขั้นตอน หากต้องการความทนทานสูงให้พิจารณา Transactional Outbox พร้อมกลไก Retry และการจัดการข้อความซ้ำ

03 Security & Reliability Decisions

ไม่เชื่อถือข้อมูลจาก Client และไม่ถือว่าการเชื่อมต่อสำเร็จ หมายถึงมีสิทธิ์เรียกทุก Action แยกการยืนยันตัวตน การตรวจสิทธิ์ และการตรวจความถูกต้องของ State ออกจากกัน

ความเสี่ยง แนวทางออกแบบ ข้อจำกัด / สิ่งที่ต้องทดสอบ
Race condition Queue ต่อ Entity ร่วมกับ Transaction และ Version Check Memory Queue ไม่ประสานหลาย Instance ต้องมีกลไกเพิ่มเติม
Malformed message จำกัด Payload และตรวจ Schema ก่อนเข้า Business Logic ปฏิเสธข้อความผิดรูปแบบ ปิด Connection เมื่อผิดร้ายแรงหรือซ้ำตามนโยบาย
Unauthorized action ตรวจสิทธิ์ทุก Action และทุก Subscription ทดสอบ Session หมดอายุ การเพิกถอนสิทธิ์ และการเข้าถึงข้ามผู้ใช้
Duplicate command ใช้ Request ID ที่ผูกผู้ใช้และตรวจซ้ำแบบ Atomic กำหนดช่วงเก็บ ID และให้การบันทึกผลอยู่ใน Transaction เดียวกัน
Resource exhaustion จำกัด Message Rate, Connection, Queue และ Outbound Buffer กำหนด Backpressure และตรวจพฤติกรรม Client ที่รับข้อมูลช้า
Sensitive data exposure ใช้ WSS กรองข้อมูลก่อน Broadcast และไม่บันทึก Token ใน Log ตรวจ Log จริง รวมถึง Error และเครื่องมือ Monitoring

ทำไมไม่ตัดการเชื่อมต่อทุกครั้งที่ข้อมูลผิด?

Validation Error ที่เกิดจากการใช้งานปกติสามารถตอบกลับแบบมีโครงสร้างได้ ส่วนข้อความที่เกินขนาด ละเมิด Protocol หรือทำผิดซ้ำ จึงใช้แนวทางปิด Connection ตามนโยบาย เพื่อรักษาสมดุลระหว่างความปลอดภัยและการใช้งาน

04 Benchmark & Measurement Plan

ส่วนนี้แสดงรูปแบบการรายงานผล ก่อนใช้เป็นผลงานจริงต้องแทนค่าด้วยผลทดสอบที่ทำซ้ำได้ พร้อมระบุเครื่องทดสอบ เวอร์ชันระบบ และลักษณะโหลด

ILLUSTRATIVE DATA / NOT MEASURED

ตัวอย่างการเปรียบเทียบ Mean Update Latency

Polling 100 ms
WebSocket 60 ms

ตัวเลขสมมติ 100 → 60 ms เท่ากับลดลง 40% เป็นตัวอย่างการคำนวณ ไม่ใช่ผล Benchmark ของโปรเจกต์ และไม่ได้หมายความว่า WebSocket จะเร็วขึ้น 40% ในทุกระบบ

ตัวชี้วัด สิ่งที่ต้องบันทึก สถานะ
Mean / p50 / p95 / p99 Latency เวลาตั้งแต่ส่ง Action จนได้รับ State ยืนยันกลับ ยังไม่มีผลวัดจริง
Concurrent Connections แผนทดสอบ 50 / 100 / 250 / 500 Connections เป้าหมายทดสอบ ไม่ใช่ความสามารถที่ยืนยันแล้ว
Event Throughput Events ต่อวินาที รวม Fan-out และ Payload Size ยังไม่กำหนด Workload จริง
CPU / Memory / Queue Depth ค่าเฉลี่ย จุดสูงสุด และพฤติกรรมเมื่อโหลดเกิน รอทดสอบ
Error / Recovery Error Rate, Reconnect Time และ State Consistency รอทดสอบ

เงื่อนไขสำหรับการเปรียบเทียบที่น่าเชื่อถือ

  • ใช้ Hardware, Dataset และ Network Conditions เดียวกัน
  • ระบุ Polling Interval, Payload Size และ Event Rate
  • แยก Idle Connections ออกจาก Connections ที่ส่งข้อมูลจริง
  • มีช่วง Warm-up และรันทดสอบซ้ำหลายรอบ
  • รายงาน Tail Latency และ Error Rate ไม่ใช้ค่าเฉลี่ยเพียงอย่างเดียว

05 Design Lessons & Next Steps

1. Transport ไม่ได้แก้ปัญหา Consistency ให้ทั้งหมด

เปลี่ยนจาก Polling เป็น WebSocket ช่วยเปลี่ยนวิธีส่งข้อมูล แต่การจัดลำดับคำสั่ง การตรวจ Version และการกู้สถานะยังต้องออกแบบแยกต่างหาก

2. Memory Queue เป็นจุดเริ่มต้น ไม่ใช่ระบบจัดคิวถาวร

Queue ในหน่วยความจำช่วยจัดลำดับภายใน Process แต่ข้อมูลอาจหายเมื่อ Process หยุด งานที่ต้องรับประกันการรับคำสั่งต้องมี Durable Storage และนิยามให้ชัดว่า ACK หมายถึงรับไว้หรือบันทึกสำเร็จแล้ว

3. เริ่มจากขอบเขตเล็ก แล้วเพิ่มความซับซ้อนจากหลักฐาน

ออกแบบ Single Instance ให้ตรวจสอบได้ก่อน เมื่อผลวัดชี้ว่าถึงข้อจำกัด จึงพิจารณา Shared Broker, Durable Queue, Transactional Outbox หรือการแบ่งเจ้าของ State

Next iteration

  • สร้าง Prototype ตามเส้นทาง Command และ State ที่ระบุ
  • เพิ่ม Integration Tests สำหรับคำสั่งซ้ำและ Version Conflict
  • ทดสอบการตัด Connection และการกู้ Snapshot
  • แทนข้อมูลตัวอย่างด้วยผล Benchmark ที่ทำซ้ำได้

// Apply this approach to your project

มีระบบที่ต้องอัปเดตข้อมูลร่วมกัน?

เล่า Workflow จำนวนผู้ใช้งาน และข้อจำกัดของระบบ เพื่อประเมินว่าควรใช้ Polling, WebSocket หรือแนวทางที่เรียบง่ายกว่าให้เหมาะกับโจทย์

Inquire for Similar Architecture ↗