Qwik Resumability Pub Sub Architecture — ออกแบบ
Qwik Pub/Sub

Qwik Resumability Pub/Sub Architecture Event-driven WebSocket SSE Real-time Redis NATS Lazy Loading Fine-grained TTI
| Transport | Direction | Use Case | Complexity |
|---|---|---|---|
| SSE (Server-Sent Events) | Server → Client | Notification, Live Feed, Price | ง่าย |
| WebSocket | Bidirectional | Chat, Collaboration, Gaming | ปานกลาง |
| Long Polling | Client → Server | Legacy Fallback | ง่าย (แต่ Inefficient) |
| WebTransport | Bidirectional | Low Latency Gaming | สูง (ใหม่) |
Qwik Component Design
// === Qwik Pub/Sub Component === // import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik'; // // interface Message { // id: string; // topic: string; // data: any; // timestamp: number; // } // // export const LiveFeed = component$(() => { // const messages = useSignal([]); // const connected = useSignal(false); // // useVisibleTask$(({ cleanup }) => { // // SSE Connection - Only runs on client, only when visible // const eventSource = new EventSource('/api/subscribe?topic=prices'); // // eventSource.onopen = () => { // connected.value = true; // }; // // eventSource.onmessage = (event) => { // const msg: Message = JSON.parse(event.data); // messages.value = [msg, ...messages.value.slice(0, 49)]; // }; // // eventSource.onerror = () => { // connected.value = false; // // Auto-reconnect built into EventSource // }; // // cleanup(() => { // eventSource.close(); // connected.value = false; // }); // }); // // return ( //Backend Pub/Sub
# === Backend Pub/Sub with Redis + SSE ===
# Server-side SSE Endpoint (Node.js / Qwik Server)
# export const onGet: RequestHandler = async ({ send, headers }) => {
# headers.set('Content-Type', 'text/event-stream');
# headers.set('Cache-Control', 'no-cache');
# headers.set('Connection', 'keep-alive');
#
# const redis = new Redis();
# await redis.subscribe('prices');
#
# redis.on('message', (channel, message) => {
# send(`data: \n\n`);
# });
# };
# Publish from another service
# import redis
# r = redis.Redis()
# r.publish('prices', json.dumps({
# 'id': str(uuid4()),
# 'topic': 'BTC/USD',
# 'data': {'price': 67500.50, 'change': 2.3},
# 'timestamp': time.time()
# }))
@dataclass
class PubSubBackend:
broker: str
protocol: str
throughput: str
persistence: str
best_for: str
backends = [
PubSubBackend("Redis Pub/Sub",
"TCP + RESP Protocol",
"100K+ msg/s",
"No (Fire & Forget)",
"Real-time ไม่ต้องเก็บ History"),
PubSubBackend("Redis Streams",
"TCP + RESP Protocol",
"100K+ msg/s",
"Yes (Append-only Log)",
"Real-time + History + Consumer Group"),
PubSubBackend("NATS",
"TCP + NATS Protocol",
"10M+ msg/s",
"Yes (JetStream)",
"High Throughput Microservices"),
PubSubBackend("Kafka",
"TCP + Kafka Protocol",
"1M+ msg/s",
"Yes (Durable Log)",
"Event Sourcing Big Data Pipeline"),
PubSubBackend("RabbitMQ",
"AMQP",
"50K+ msg/s",
"Yes (Queue)",
"Task Queue Complex Routing"),
]
print("=== Pub/Sub Backends ===")
for b in backends:
print(f"\n [{b.broker}] Protocol: {b.protocol}")
print(f" Throughput: {b.throughput}")
print(f" Persistence: {b.persistence}")
print(f" Best for: {b.best_for}")
Production Patterns
# === Production Patterns ===
@dataclass
class ProdPattern:
pattern: str
problem: str
solution: str
implementation: str
prod_patterns = [
ProdPattern("Reconnection with Backoff",
"Connection หลุดจาก Network Issue",
"Exponential Backoff: 1s 2s 4s 8s max 30s",
"SSE มี Auto-reconnect WS ต้องเขียนเอง"),
ProdPattern("Authentication",
"Unauthorized Subscribe",
"ส่ง JWT Token ใน URL param หรือ First Message",
"EventSource('/api/sub?token=xxx') หรือ WS onopen"),
ProdPattern("Topic-based Filtering",
"ไม่อยากรับทุก Message",
"Subscribe เฉพาะ Topic ที่สนใจ",
"redis.subscribe('prices:BTC', 'prices:ETH')"),
ProdPattern("Heartbeat / Keep-alive",
"Connection timeout จาก Proxy/LB",
"ส่ง Heartbeat ทุก 30 วินาที",
"setInterval(() => send(':heartbeat'), 30000)"),
ProdPattern("Message Deduplication",
"ได้ Message ซ้ำจาก Reconnect",
"ใช้ Message ID + Last Event ID",
"EventSource lastEventId, Server filter dup"),
ProdPattern("Cleanup on Unmount",
"Memory Leak จาก Connection ค้าง",
"Close Connection เมื่อ Component Unmount",
"useVisibleTask$ cleanup() callback"),
]
print("=== Production Patterns ===")
for p in prod_patterns:
print(f" [{p.pattern}]")
print(f" Problem: {p.problem}")
print(f" Solution: {p.solution}")
print(f" Impl: {p.implementation}")
เคล็ดลับ

- SSE: ใช้ SSE ถ้าต้องการแค่ Server Push ง่ายกว่า WebSocket
- useVisibleTask$: เชื่อมต่อเฉพาะเมื่อ Component Visible ลด Resource
- cleanup: ปิด Connection ใน cleanup() ทุกครั้ง ป้องกัน Memory Leak
- Redis Streams: ใช้แทน Pub/Sub ถ้าต้องเก็บ History
- Heartbeat: ส่ง Heartbeat ทุก 30s ป้องกัน Proxy ตัด Connection
Qwik Resumability คืออะไร
Web Framework Resumability แทน Hydration Zero JS TTI เร็ว Lazy Loading Fine-grained $ sign component$ useTask$ onClick$
เนื้อหาเกี่ยวข้อง — อ่านต่อ: Btrfs Filesystem Incident Management
อ่านเพิ่ม: WebSocket คืออะไร? สอนสร้างระบบ Real-time ด้วย WebSocket, SS · อ่านเพิ่ม: Redis คืออะไร? สอน Caching ตั้งแต่ In-Memory Store Session Q · อ่านเพิ่ม: Push Notification คืออะไร? สอนสร้างระบบ Push และ Real-time ส
Pub/Sub Pattern คืออะไร
Publisher Subscriber Topic Broker Decoupled Redis NATS Kafka RabbitMQ Scalable Real-time WebSocket SSE Notification Chat Dashboard
แนะนำเพิ่มเติม — เรียนเทรดกับ iCafeForex
เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: rancher kubernetes คือ — คู่มือฉบับสมบูรณ์ 2026
ใช้กับ Qwik อย่างไร
useVisibleTask$ SSE WebSocket useSignal useStore server$ routeLoader$ routeAction$ EventSource cleanup Reactive State Real-time
เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: database คืออะไร — วิธีตั้งค่าและใช้งานจริงพร้อมตัวอย่าง
Production Best Practices คืออะไร
SSE ง่ายกว่า WS Reconnection Backoff Auth JWT Token Topic Filter Heartbeat Dedup Message ID Cleanup Unmount Rate Limiting Dead Letter
แนะนำเพิ่มเติม — XM Signal
สรุป
Qwik Resumability Pub/Sub SSE WebSocket Redis NATS useVisibleTask$ useSignal Lazy Loading Real-time Reconnection Heartbeat Production
เนื้อหาเกี่ยวข้อง — ONNX Runtime Clean Architecture





