JavaScript Bun Runtime Pub Sub Architecture — คู่มือฉบับสมบูรณ์ 2026 | SiamCafe Blog

JavaScript Bun Runtime Pub Sub Architecture — คู่มือฉบับสมบูรณ์ 2026 | SiamCafe Blog

แนะนำระบบ Pub Sub บน Bun Runtime

ในโลกของการพัฒนาแอปพลิเคชันสมัยใหม่ การสื่อสารระหว่างส่วนประกอบต่างๆ ของระบบเป็นสิ่งที่ท้าทายมากขึ้นเรื่อยๆ โดยเฉพาะเมื่อเราต้องการสร้างระบบที่สามารถขยายขนาดได้ (scalable) และตอบสนองได้แบบเรียลไทม์ (real-time) หนึ่งในรูปแบบสถาปัตยกรรมที่ได้รับความนิยมมากที่สุดคือ Pub/Sub (Publish/Subscribe) ซึ่งช่วยให้ระบบสามารถส่งข้อความระหว่างผู้ส่งและผู้รับโดยไม่ต้อง耦合กันโดยตรง

Bun เป็น JavaScript runtime ตัวใหม่ที่ถูกออกแบบมาเพื่อความเร็วสูง โดยใช้ JavaScriptCore engine แทน V8 ทำให้สามารถรัน JavaScript และ TypeScript ได้เร็วกว่า Node.js ถึง 4 เท่าในหลายๆ กรณี นอกจากนี้ Bun ยังมี built-in APIs ที่ทรงพลังสำหรับการเขียนระบบ Pub/Sub โดยเฉพาะอย่างยิ่งกับ WebSocket และ HTTP ซึ่งเป็นรากฐานสำคัญของการสร้าง real-time applications

ในบทความนี้ เราจะเจาะลึกถึงสถาปัตยกรรม Pub/Sub บน Bun Runtime ตั้งแต่พื้นฐานไปจนถึงการใช้งานจริง พร้อมตัวอย่างโค้ดที่สามารถนำไปปรับใช้ได้ทันที

พื้นฐานของ Pub/Sub Architecture

หลักการทำงานของ Pub/Sub

Pub/Sub (Publish/Subscribe) เป็นรูปแบบการส่งข้อความ (messaging pattern) ที่ประกอบด้วยสามองค์ประกอบหลัก:

  • Publisher (ผู้เผยแพร่) – ส่งข้อความไปยังช่องทาง (channel/topic) โดยไม่จำเป็นต้องรู้ว่ามีใครรับบ้าง
  • Subscriber (ผู้สมัครรับ) – ลงทะเบียนเพื่อรับข้อความจากช่องทางที่สนใจ
  • Broker (ตัวกลาง) – ทำหน้าที่จัดการการส่งต่อข้อความจาก publisher ไปยัง subscriber ที่เกี่ยวข้อง

ข้อดีของสถาปัตยกรรมนี้คือการลด coupling ระหว่างส่วนประกอบต่างๆ ทำให้ระบบมีความยืดหยุ่นสูง สามารถเพิ่มหรือลด subscriber ได้โดยไม่กระทบต่อ publisher และรองรับการทำงานแบบ asynchronous

ความแตกต่างระหว่าง Pub/Sub กับ Message Queue

คุณสมบัติ Pub/Sub Message Queue
รูปแบบการส่ง Broadcast (หนึ่งต่อหลาย) Point-to-point (หนึ่งต่อหนึ่ง)
การคงอยู่ของข้อความ ข้อความจะหายไปถ้าไม่มี subscriber ข้อความจะถูกเก็บไว้จนกว่าผู้รับจะรับไป
ความสัมพันธ์ Publisher ไม่รู้จัก subscriber Producer รู้จัก consumer
การใช้งานที่เหมาะสม Real-time notifications, event streaming Task queue, workload distribution

Bun Runtime: จุดเด่นสำหรับ Pub/Sub

ประสิทธิภาพและความเร็ว

Bun ถูกออกแบบมาให้เป็น all-in-one toolkit สำหรับ JavaScript/TypeScript โดยมีคุณสมบัติที่โดดเด่นหลายประการที่ทำให้เหมาะกับการสร้างระบบ Pub/Sub:

  • WebSocket เบื้องต้น – Bun มี WebSocket server และ client ในตัว ไม่ต้องพึ่งพาไลบรารีภายนอก
  • HTTP/2 และ HTTP/3 support – รองรับการสื่อสารแบบ multiplexing และ low-latency
  • Native TypeScript support – ไม่ต้อง transpile ก่อน run
  • SQLite integration – สามารถใช้เป็น persistent storage สำหรับข้อความ
  • ตัวจัดการแพคเกจในตัว – bun install เร็วกว่า npm ถึง 10-30 เท่า

การจัดการ Event Loop

Bun ใช้ JavaScriptCore engine ซึ่งมี event loop ที่มีประสิทธิภาพสูงกว่า V8 ในบางกรณี โดยเฉพาะการจัดการ I/O operations จำนวนมากพร้อมกัน ซึ่งเป็นหัวใจสำคัญของระบบ Pub/Sub ที่ต้องรองรับ connections หลายพันรายการ

นอกจากนี้ Bun ยังมี built-in APIs สำหรับการทำงานแบบ concurrent เช่น Bun.sleep(), Bun.write(), และ Bun.connect() ที่ช่วยให้การเขียนโค้ด Pub/Sub ทำได้ง่ายและมีประสิทธิภาพ

การสร้าง Pub/Sub System ด้วย Bun

สถาปัตยกรรมพื้นฐาน

ในส่วนนี้เราจะสร้างระบบ Pub/Sub อย่างง่ายโดยใช้ WebSocket และ in-memory event bus บน Bun โดยเริ่มจากตัวอย่างการสร้าง server และ client

ตัวอย่างที่ 1: In-Memory Pub/Sub

// pubsub.ts - Simple in-memory Pub/Sub implementation
type Subscriber = (message: string, topic: string) => void;

class PubSub {
  private subscribers: Map<string, Set<Subscriber>> = new Map();

  subscribe(topic: string, callback: Subscriber): () => void {
    if (!this.subscribers.has(topic)) {
      this.subscribers.set(topic, new Set());
    }
    
    this.subscribers.get(topic)!.add(callback);
    
    // Return unsubscribe function
    return () => {
      this.subscribers.get(topic)?.delete(callback);
    };
  }

  publish(topic: string, message: string): void {
    const subs = this.subscribers.get(topic);
    if (subs) {
      subs.forEach(callback => {
        // Use setTimeout to make it async
        setTimeout(() => callback(message, topic), 0);
      });
    }
  }

  getTopics(): string[] {
    return Array.from(this.subscribers.keys());
  }

  subscriberCount(topic: string): number {
    return this.subscribers.get(topic)?.size ?? 0;
  }
}

// Usage example
const bus = new PubSub();

const unsubscribe = bus.subscribe('user.login', (msg) => {
  console.log(`[User Login]: ${msg}`);
});

bus.subscribe('system.alert', (msg) => {
  console.log(`[Alert]: ${msg}`);
});

bus.publish('user.login', 'User 123 has logged in');
bus.publish('system.alert', 'CPU usage exceeded 90%');

// Unsubscribe when no longer needed
unsubscribe();

console.log('Active topics:', bus.getTopics());

ตัวอย่างที่ 2: WebSocket Pub/Sub Server

ต่อไปเราจะสร้าง WebSocket server ที่สามารถจัดการ Pub/Sub ได้แบบ real-time โดยใช้ Bun’s built-in WebSocket API

// websocket-pubsub.ts - WebSocket Pub/Sub Server
import { ServerWebSocket } from 'bun';

interface ClientInfo {
  socket: ServerWebSocket;
  subscribedTopics: Set<string>;
  userId: string;
}

class WebSocketPubSub {
  private clients: Map<string, ClientInfo> = new Map();
  private topicClients: Map<string, Set<string>> = new Map();

  addClient(socket: ServerWebSocket, userId: string): void {
    this.clients.set(userId, {
      socket,
      subscribedTopics: new Set(),
      userId
    });
    
    console.log(`Client ${userId} connected. Total clients: ${this.clients.size}`);
  }

  removeClient(userId: string): void {
    const client = this.clients.get(userId);
    if (client) {
      // Remove from all topics
      client.subscribedTopics.forEach(topic => {
        this.topicClients.get(topic)?.delete(userId);
      });
      
      this.clients.delete(userId);
      console.log(`Client ${userId} disconnected. Total clients: ${this.clients.size}`);
    }
  }

  subscribe(userId: string, topic: string): boolean {
    const client = this.clients.get(userId);
    if (!client) return false;

    if (!this.topicClients.has(topic)) {
      this.topicClients.set(topic, new Set());
    }

    this.topicClients.get(topic)!.add(userId);
    client.subscribedTopics.add(topic);
    
    console.log(`Client ${userId} subscribed to ${topic}`);
    return true;
  }

  unsubscribe(userId: string, topic: string): boolean {
    const client = this.clients.get(userId);
    if (!client) return false;

    this.topicClients.get(topic)?.delete(userId);
    client.subscribedTopics.delete(topic);
    
    console.log(`Client ${userId} unsubscribed from ${topic}`);
    return true;
  }

  publish(topic: string, message: string, senderId?: string): void {
    const subscribers = this.topicClients.get(topic);
    if (!subscribers) return;

    const payload = JSON.stringify({
      type: 'message',
      topic,
      data: message,
      timestamp: new Date().toISOString(),
      sender: senderId || 'system'
    });

    subscribers.forEach(clientId => {
      const client = this.clients.get(clientId);
      if (client && client.socket.readyState === WebSocket.OPEN) {
        client.socket.send(payload);
      }
    });
  }

  getStats(): object {
    return {
      totalClients: this.clients.size,
      totalTopics: this.topicClients.size,
      topicDetails: Array.from(this.topicClients.entries()).map(([topic, clients]) => ({
        topic,
        subscriberCount: clients.size
      }))
    };
  }
}

// Server setup
const pubsub = new WebSocketPubSub();

Bun.serve({
  port: 3000,
  fetch(req, server) {
    // Handle HTTP upgrade to WebSocket
    if (server.upgrade(req)) {
      return; // Return undefined to let Bun handle it
    }
    
    // Serve a simple client page
    return new Response('WebSocket Pub/Sub Server is running', {
      headers: { 'Content-Type': 'text/plain' }
    });
  },
  websocket: {
    open(ws) {
      // Generate a unique ID for each connection
      const userId = `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      ws.data = { userId };
      pubsub.addClient(ws, userId);
      
      // Send welcome message with client ID
      ws.send(JSON.stringify({
        type: 'welcome',
        userId,
        message: 'Connected to Pub/Sub server'
      }));
    },
    
    message(ws, rawMessage) {
      try {
        const message = JSON.parse(rawMessage.toString());
        const { userId } = ws.data;
        
        switch (message.type) {
          case 'subscribe':
            pubsub.subscribe(userId, message.topic);
            ws.send(JSON.stringify({
              type: 'subscribed',
              topic: message.topic,
              success: true
            }));
            break;
            
          case 'unsubscribe':
            pubsub.unsubscribe(userId, message.topic);
            ws.send(JSON.stringify({
              type: 'unsubscribed',
              topic: message.topic,
              success: true
            }));
            break;
            
          case 'publish':
            pubsub.publish(message.topic, message.data, userId);
            break;
            
          case 'stats':
            ws.send(JSON.stringify({
              type: 'stats',
              data: pubsub.getStats()
            }));
            break;
            
          default:
            ws.send(JSON.stringify({
              type: 'error',
              message: `Unknown message type: ${message.type}`
            }));
        }
      } catch (error) {
        ws.send(JSON.stringify({
          type: 'error',
          message: 'Invalid message format'
        }));
      }
    },
    
    close(ws) {
      const { userId } = ws.data;
      if (userId) {
        pubsub.removeClient(userId);
      }
    }
  }
});

console.log('WebSocket Pub/Sub server running on ws://localhost:3000');

ตัวอย่างที่ 3: Client-side WebSocket

// client.ts - WebSocket Client Example
const ws = new WebSocket('ws://localhost:3000');

ws.onopen = () => {
  console.log('Connected to server');
  
  // Subscribe to topics
  ws.send(JSON.stringify({
    type: 'subscribe',
    topic: 'notifications'
  }));
  
  ws.send(JSON.stringify({
    type: 'subscribe',
    topic: 'chat.room1'
  }));
  
  // Publish a message
  ws.send(JSON.stringify({
    type: 'publish',
    topic: 'chat.room1',
    data: 'Hello everyone!'
  }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log('Received:', message);
  
  switch (message.type) {
    case 'welcome':
      console.log(`Your user ID: ${message.userId}`);
      break;
      
    case 'message':
      console.log(`[${message.topic}] ${message.sender}: ${message.data}`);
      break;
      
    case 'subscribed':
      console.log(`Successfully subscribed to ${message.topic}`);
      break;
  }
};

ws.onclose = () => {
  console.log('Disconnected from server');
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

การออกแบบระบบ Pub/Sub ขนาดใหญ่

การจัดการ Scaling

เมื่อระบบมีผู้ใช้จำนวนมาก การใช้ in-memory Pub/Sub เพียงอย่างเดียวอาจไม่เพียงพอ เนื่องจากข้อจำกัดด้านหน่วยความจำและความสามารถในการประมวลผลของเครื่องเดียว เราจำเป็นต้องออกแบบระบบให้สามารถขยายขนาดได้ (horizontally scalable) โดยใช้กลยุทธ์ต่อไปนี้:

  1. Redis Pub/Sub – ใช้ Redis เป็น message broker กลางสำหรับการสื่อสารระหว่าง Bun instances หลายตัว
  2. Message Queue Integration – เชื่อมต่อกับ RabbitMQ, Kafka หรือ NATS สำหรับการจัดการข้อความที่มีความน่าเชื่อถือสูง
  3. Load Balancing – ใช้ NGINX หรือ HAProxy เพื่อกระจาย WebSocket connections ไปยัง servers หลายตัว
  4. Sharding – แบ่ง topics ออกเป็นกลุ่มๆ และมอบหมายให้ servers ต่างๆ รับผิดชอบ

การเชื่อมต่อกับ Redis สำหรับ Pub/Sub

ตัวอย่างการเชื่อมต่อ Pub/Sub กับ Redis เพื่อให้สามารถทำงานข้าม instances ได้:

// redis-pubsub.ts - Redis-backed Pub/Sub for horizontal scaling
import { Redis } from 'ioredis';

class RedisPubSub {
  private redis: Redis;
  private subRedis: Redis;
  private localHandlers: Map<string, Set<(message: string) => void>> = new Map();

  constructor(redisUrl: string = 'redis://localhost:6379') {
    this.redis = new Redis(redisUrl);
    this.subRedis = new Redis(redisUrl);
    
    // Listen for messages from Redis
    this.subRedis.on('message', (channel, message) => {
      const handlers = this.localHandlers.get(channel);
      if (handlers) {
        handlers.forEach(handler => handler(message));
      }
    });
  }

  async subscribe(topic: string, handler: (message: string) => void): Promise<() => Promise<void>> {
    // Register local handler
    if (!this.localHandlers.has(topic)) {
      this.localHandlers.set(topic, new Set());
      // Subscribe to Redis channel
      await this.subRedis.subscribe(topic);
    }
    
    this.localHandlers.get(topic)!.add(handler);
    
    // Return unsubscribe function
    return async () => {
      this.localHandlers.get(topic)?.delete(handler);
      if (this.localHandlers.get(topic)?.size === 0) {
        await this.subRedis.unsubscribe(topic);
        this.localHandlers.delete(topic);
      }
    };
  }

  async publish(topic: string, message: string): Promise<void> {
    await this.redis.publish(topic, message);
  }

  async disconnect(): Promise<void> {
    await this.redis.quit();
    await this.subRedis.quit();
  }
}

// Usage
const pubsub = new RedisPubSub();

// Subscribe
await pubsub.subscribe('orders.new', (message) => {
  console.log('New order:', message);
});

// Publish
await pubsub.publish('orders.new', JSON.stringify({
  orderId: 'ORD-123',
  userId: 'user_456',
  amount: 2500
}));

การเปรียบเทียบไลบรารี Pub/Sub สำหรับ Bun

ไลบรารี ประเภท ข้อดี ข้อเสีย เหมาะสำหรับ
Bun WebSocket (built-in) Real-time ไม่ต้องติดตั้งเพิ่ม, ความเร็วสูง, รองรับ TypeScript ฟังก์ชันจำกัด, ไม่มี persistence แอปพลิเคชันขนาดเล็ก-กลาง, real-time chat
Redis Pub/Sub Message Broker รองรับหลายภาษา, persistence options, scalability ต้องติดตั้ง Redis, latency สูงกว่า in-memory ระบบที่ต้องการ scaling และความน่าเชื่อถือสูง
RabbitMQ (amqplib) Message Queue รองรับ routing complex, message acknowledgment การตั้งค่าซับซ้อน, overhead สูง ระบบ enterprise ที่ต้องการ guaranteed delivery
NATS Cloud-native Messaging ความเร็วสูง, รองรับ clustering, at-most-once delivery ฟังก์ชันน้อยกว่า RabbitMQ Microservices, IoT, edge computing
Socket.IO (Bun compatible) Real-time Framework fallback transport, rooms, namespaces overhead สูงกว่า raw WebSocket แอปพลิเคชันที่ต้องการ compatibility สูง

Best Practices สำหรับ Pub/Sub บน Bun

การจัดการ Connection

  • ใช้ Connection Pool – สำหรับ Redis หรือ database connections ควรใช้ pooling เพื่อลด overhead
  • Heartbeat Mechanism – ส่ง ping/packet เป็นระยะเพื่อตรวจจับ connection ที่หลุด
  • Graceful Shutdown – จัดการ cleanup เมื่อ server ปิดตัวลง เช่น การ unsubscribe ทั้งหมด
  • Rate Limiting – ป้องกัน abuse โดยจำกัดจำนวนข้อความที่ client สามารถ publish ได้

การออกแบบ Topic

  • ใช้ Hierarchy – เช่น orders.created, orders.shipped แทน order1, order2
  • Wildcard Support – รองรับการ subscribe ด้วย pattern เช่น orders.*
  • Namespace – แยก topics ตาม domain เพื่อป้องกันชื่อซ้ำ
  • Documentation – สร้างเอกสารสำหรับทุก topic ที่มีในระบบ

การจัดการข้อความ

  • Message Validation – ตรวจสอบรูปแบบข้อความก่อนส่งต่อ
  • Idempotency – ออกแบบให้ subscriber สามารถรับข้อความซ้ำได้โดยไม่มีผลข้างเคียง
  • Backpressure – จัดการเมื่อ subscriber ประมวลผลไม่ทัน โดยใช้ buffer หรือ queue
  • Logging – บันทึกทุกการ publish และ subscribe เพื่อการ debug

Real-World Use Cases

1. ระบบแจ้งเตือนแบบ Real-time

แพลตฟอร์มอีคอมเมิร์ซใช้ Pub/Sub เพื่อแจ้งเตือนผู้ใช้เมื่อมีคำสั่งซื้อใหม่ การชำระเงินสำเร็จ หรือสถานะการจัดส่งเปลี่ยนแปลง โดยแต่ละเหตุการณ์จะถูก publish ไปยัง topic ที่เกี่ยวข้อง และ subscriber จะแสดง notification ผ่าน WebSocket ทันที

2. ระบบ Chat Application

แอปพลิเคชันแชทใช้ Pub/Sub เพื่อส่งข้อความระหว่างผู้ใช้ โดยแต่ละห้องแชทจะเป็น topic หนึ่ง เมื่อมีผู้ใช้ส่งข้อความ ข้อความนั้นจะถูก publish ไปยัง topic ของห้อง และทุกคนที่ subscribe อยู่จะได้รับข้อความแบบ real-time

3. IoT Data Streaming

ระบบ IoT ใช้ Pub/Sub เพื่อรวบรวมข้อมูลจากเซนเซอร์หลายพันตัว โดยเซนเซอร์แต่ละตัวทำหน้าที่เป็น publisher ส่งข้อมูลไปยัง topic ตามประเภท (เช่น temperature, humidity) และระบบ backend จะ subscribe เพื่อประมวลผลและจัดเก็บข้อมูลต่อไป

4. Microservices Communication

ในสถาปัตยกรรม microservices, Pub/Sub ใช้สำหรับการสื่อสารแบบ asynchronous ระหว่าง services เช่น เมื่อ service หนึ่งสร้างคำสั่งซื้อเสร็จ มันจะ publish เหตุการณ์ไปยัง topic order.created ซึ่ง service อื่นๆ เช่น inventory service และ notification service จะ subscribe และดำเนินการตามหน้าที่ของตน

การทดสอบและ Debug ระบบ Pub/Sub

เครื่องมือที่แนะนำ

  • Bun Test Runner – ใช้ bun test สำหรับ unit testing components
  • WebSocket Client Tools – เช่น wscat หรือ websocat สำหรับทดสอบด้วย CLI
  • RedisInsight – สำหรับตรวจสอบ Redis Pub/Sub channels
  • Custom Dashboard – สร้างหน้าเว็บสำหรับตรวจสอบสถานะระบบ

ตัวอย่างการทดสอบ Pub/Sub

// pubsub.test.ts - Unit test for PubSub system
import { describe, expect, test, mock } from 'bun:test';
import { PubSub } from './pubsub';

describe('PubSub System', () => {
  test('should deliver messages to subscribers', () => {
    const bus = new PubSub();
    const handler = mock((msg: string) => {});
    
    bus.subscribe('test', handler);
    bus.publish('test', 'hello');
    
    // Wait for async execution
    setTimeout(() => {
      expect(handler).toHaveBeenCalledWith('hello', 'test');
    }, 10);
  });
  
  test('should not deliver to unsubscribed topics', () => {
    const bus = new PubSub();
    const handler = mock(() => {});
    
    bus.subscribe('topic1', handler);
    bus.publish('topic2', 'data');
    
    setTimeout(() => {
      expect(handler).not.toHaveBeenCalled();
    }, 10);
  });
  
  test('should support multiple subscribers', () => {
    const bus = new PubSub();
    const handler1 = mock(() => {});
    const handler2 = mock(() => {});
    
    bus.subscribe('topic', handler1);
    bus.subscribe('topic', handler2);
    bus.publish('topic', 'data');
    
    setTimeout(() => {
      expect(handler1).toHaveBeenCalledTimes(1);
      expect(handler2).toHaveBeenCalledTimes(1);
    }, 10);
  });
  
  test('should allow unsubscribe', () => {
    const bus = new PubSub();
    const handler = mock(() => {});
    
    const unsubscribe = bus.subscribe('topic', handler);
    unsubscribe();
    bus.publish('topic', 'data');
    
    setTimeout(() => {
      expect(handler).not.toHaveBeenCalled();
    }, 10);
  });
  
  test('should track subscriber count per topic', () => {
    const bus = new PubSub();
    
    bus.subscribe('topic1', () => {});
    bus.subscribe('topic1', () => {});
    bus.subscribe('topic2', () => {});
    
    expect(bus.subscriberCount('topic1')).toBe(2);
    expect(bus.subscriberCount('topic2')).toBe(1);
  });
});

การเพิ่มประสิทธิภาพ (Performance Optimization)

การจัดการหน่วยความจำ

เมื่อมี subscriber จำนวนมาก การเก็บ callback functions ทั้งหมดในหน่วยความจำอาจทำให้เกิด memory leak ได้ ควรใช้ WeakMap หรือ implement reference counting เพื่อให้ garbage collector สามารถเก็บ callback ที่ไม่ได้ใช้งานแล้วได้

การบีบอัดข้อความ

สำหรับข้อความขนาดใหญ่ ควรพิจารณาการบีบอัด (compression) ก่อนส่งผ่าน WebSocket โดย Bun รองรับ compression ผ่าน WebSocket permessage-deflate extension

การจำกัดความถี่ (Throttling)

ในบางกรณี subscriber อาจไม่สามารถรับข้อความได้ทันตามความเร็วที่ publisher ส่งมา ควรใช้เทคนิค throttling หรือ batching เพื่อลดภาระ:

// throttled-subscriber.ts
class ThrottledSubscriber {
  private buffer: string[] = [];
  private timer: Timer | null = null;
  private readonly interval: number;
  private readonly handler: (messages: string[]) => void;

  constructor(handler: (messages: string[]) => void, intervalMs: number = 100) {
    this.handler = handler;
    this.interval = intervalMs;
  }

  receive(message: string): void {
    this.buffer.push(message);
    
    if (!this.timer) {
      this.timer = setTimeout(() => {
        this.flush();
      }, this.interval);
    }
  }

  private flush(): void {
    if (this.buffer.length > 0) {
      const messages = [...this.buffer];
      this.buffer = [];
      this.handler(messages);
    }
    this.timer = null;
  }

  destroy(): void {
    if (this.timer) {
      clearTimeout(this.timer);
      this.flush();
    }
  }
}

// Usage
const subscriber = new ThrottledSubscriber((messages) => {
  console.log(`Processing ${messages.length} messages at once`);
  // Process batch
}, 200);

// Simulate fast messages
for (let i = 0; i < 100; i++) {
  subscriber.receive(`Message ${i}`);
}

ความปลอดภัยในระบบ Pub/Sub

การ Authentication และ Authorization

  • Token-based Authentication - ใช้ JWT หรือ API keys สำหรับ verify identity
  • Topic-level Authorization - ควบคุมว่า subscriber แต่ละคนสามารถเข้าถึง topic ใดได้บ้าง
  • Rate Limiting - ป้องกันการ publish ข้อความจำนวนมากเกินไป
  • Message Encryption - เข้ารหัสข้อความที่ sensitive ก่อนส่ง

การป้องกัน DoS Attacks

  • จำกัดขนาดของข้อความสูงสุด
  • ใช้ connection limits ต่อ IP
  • implement backpressure mechanism
  • มีระบบตรวจจับพฤติกรรมผิดปกติ

สรุป

สถาปัตยกรรม Pub/Sub บน Bun Runtime เป็นทางเลือกที่ทรงพลังสำหรับการสร้างระบบ real-time ที่ต้องการประสิทธิภาพสูงและความสามารถในการขยายขนาด ด้วย built-in WebSocket support และความเร็วที่เหนือกว่า Node.js ทำให้ Bun เป็นตัวเลือกที่น่าสนใจสำหรับนักพัฒนาที่ต้องการสร้างแอปพลิเคชันแบบ event-driven

จากบทความนี้ เราได้เรียนรู้:

  • พื้นฐานของ Pub/Sub และความแตกต่างจาก Message Queue
  • การสร้างระบบ Pub/Sub ตั้งแต่แบบ in-memory ไปจนถึงการเชื่อมต่อกับ Redis
  • เทคนิคการออกแบบสำหรับระบบขนาดใหญ่และการ scaling
  • การเปรียบเทียบเครื่องมือและไลบรารีต่างๆ
  • แนวทางปฏิบัติที่ดีที่สุด (best practices) สำหรับการใช้งานจริง

การเลือกใช้เครื่องมือและสถาปัตยกรรมที่เหมาะสมขึ้นอยู่กับความต้องการเฉพาะของแต่ละโครงการ สำหรับแอปพลิเคชันขนาดเล็กถึงกลาง การใช้ built-in WebSocket ของ Bun ร่วมกับ in-memory Pub/Sub ก็เพียงพอแล้ว แต่สำหรับระบบ enterprise ที่ต้องการความน่าเชื่อถือสูงและความสามารถในการขยายขนาด ควรพิจารณาใช้ Redis หรือ message broker อื่นๆ ร่วมด้วย

ในปี 2026 และต่อๆ ไป เราคาดว่า Bun จะมีการพัฒนาเพิ่มเติมเพื่อรองรับระบบ Pub/Sub โดยตรงมากขึ้น รวมถึงการปรับปรุง performance และการเพิ่ม built-in features ที่จะทำให้การพัฒนา real-time applications ทำได้ง่ายและมีประสิทธิภาพยิ่งขึ้น

ท้ายที่สุด การทดสอบและการ monitor ระบบอย่างสม่ำเสมอเป็นสิ่งสำคัญ ไม่ว่าคุณจะเลือกใช้เครื่องมือหรือสถาปัตยกรรมใด การมีระบบ logging และ metrics ที่ดีจะช่วยให้คุณสามารถตรวจจับปัญหาและปรับปรุงประสิทธิภาพได้อย่างต่อเนื่อง

จัดส่งรวดเร็วส่งด่วนทั่วประเทศ
รับประกันสินค้าเคลมง่าย มีใบรับประกัน
ผ่อนชำระได้บัตรเครดิต 0% สูงสุด 10 เดือน
สะสมแต้ม รับส่วนลดส่วนลดและคะแนนสะสม

© 2026 SiamLancard — จำหน่ายการ์ดแลน อุปกรณ์ Server และเครื่องพิมพ์ใบเสร็จ

SiamLancard
Logo
Free Forex EA — XM Signal · SiamCafe Blog · SiamLancard · Siam2R · iCafeFX
iCafeForex.com - สอนเทรด Forex | SiamCafe.net
Shopping cart