Redis Pub/Sub กับ Node.js ระดับ 101
มาหัดทำ Redis Publish/Subscribe ด้วย Node.js ที่เรารักกันนะ
ใน Blog นี้ ในส่วนแรก จะอธิบายถึง Pub/Sub ว่าหมายถึงอะไร และในส่วนหลังจะเป็นตัวอย่างการ Implement ของ Redis Pub/Sub กับ Node.js ครับ
Pub/Sub (Publish/Subscribe) คืออะไร
Pub/Sub เป็นรูปแบบการส่งข้อความ (Message) จากผู้ส่ง (Publisher) ไปยังผู้รับ (Subscriber) โดยที่ผู้ส่งและผู้รับ จะตกลงสื่อสารกันด้วยหัวข้อ (Topic) ผ่านตัวกลาง/ช่องทาง (Medium/Channel) ที่กำหนดไว้แล้ว
องค์ประกอบสำคัญของ Pub/Sub
Publisher
ผู้ส่ง Message/Event
Channel
ช่องทางการสื่อการ บางครั้งอาจจะเรียกว่า Broker, Message broker, Event bus หรือ Queue messaging ก็ได้
Subscriber
ผู้รับ Message/Event
Topic
หัวข้อของ Message/Event ที่ใช้สื่อสารกัน
ยกตัวอย่างที่น่าจะทำให้เข้าได้ง่ายขึ้น (อาจจะไม่ถูกต้อง 100%)
ให้นึกถึงบอร์ดประกาศข่าวสาร (Medium/Channel) เมื่อผู้ที่ต้องประกาศข่าว (Publisher) เอาตัวประกาศ (Message) มาติดที่บอร์ด โดยที่ตัวประกาศเอง ก็มีหัวข้อที่ชัดเจน แล้วมีผู้ที่ต้องการทราบประกาศ (Subscriber) โดยรู้ว่าต้องการอ่านประกาศจากหัวข้ออะไร (Topic) มาอ่านประกาศนั้น ๆ
จากตัวอย่างนี้จะพบว่าผู้ประกาศไม่จำเป็นต้องรู้ว่าผู้รับประกาศคือใคร และเช่นเดียวกัน ผู้รับประกาศก็ไม่จำเป็นต้องรู้ว่าใครคือผู้ประกาศ แต่ทั้งคู่จำเป็นต้องทราบว่าจะใช้ตัวบอร์ดประกาศ และหัวข้ออะไรในการสื่อสาร
publish–subscribe is a messaging pattern where senders is messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead categorize published messages into classes without knowledge of which subscribers
Redis Pub/Sub x Node.js Implementation
ในตัวอย่างนี้จะใช้งาน Redis ผ่าน Container เนื่องจากเป็นวิธีที่สะดวกที่สุดแล้วนะครับ ส่วนตัว Node.js Application ก็จะเขียนด้วย Javascript ธรรมดาครับ และ Code ทั้งหมดจะอยู่ที่ https://github.com/puuga/hello-redis-pub-sub-x-nodejs
Redis Container
สามารถเลือกใช้ Image ได้จาก https://hub.docker.com/_/redis
จากนั้นสั่งให้สร้าง Container ขึ้นมา
docker run --name my-redis -d -p 6379:6379 redis:6-alpine
เพื่อความแน่ใจ ลองใช้คำสั่ง docker container ls
เพื่อตรวจสอบว่ามี Redis Container ทำงานหรือยัง
docker container ls
Publisher Node.js Application
Note: Code ทั้งหมดของ publish.js จะอยู่ที่ https://github.com/puuga/hello-redis-pub-sub-x-nodejs/blob/main/publish.js
ในส่วนของการ Publish Message เราจะทำตาม Redis Library หน้าตาของ Code ที่ได้ จะประมาณนี้ครับ
const client = createClient();
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();const publisher = client.duplicate();
await publisher.connect();
await publisher.publish(topic, message);
Subscriber Node.js Application
Note: Code ทั้งหมดของ publish.js จะอยู่ที่ https://github.com/puuga/hello-redis-pub-sub-x-nodejs/blob/main/subscribe.js
ในส่วนของการ Subscribe Message เราจะทำตาม Library Redis หน้าตาของ Code ที่ได้ จะประมาณนี้ครับ
const client = createClient();
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();const subscriber = client.duplicate();
await subscriber.connect();
await subscriber.subscribe(topic, (message) => {
console.log('Got message from topic:', topic);
console.log(message); // 'message'
});
Let Them Fight
ในการทดลองทำ Pub/Sub จะทดลองโดยการสื่อสารผ่าน 2 Topics คือ topic1 และ topic2 จาก publisher1, publisher2 และ subscriber1_1, subscriber2_1 และ subscriber3_2
ออกแบบการส่งข้อความตามลำดับดังนี้
- ให้ subscriber1_1, subscriber2_1 และ subscriber3_1 เริ่มทำงาน
- publisher1 สื่อสารโดยใช้ topic1 โดยมี subscriber1_1 และ subscriber2_1
- publisher2 สื่อสารโดยใช้ topic2 โดยมี subscriber3_2
1. ให้ subscriber1_1, subscriber2_1 และ subscriber3_1 เริ่มทำงาน
แสดง subscriber1_1, subscriber2_1 และ subscriber3_1 เรียงตามลำดับจากบนลงล่าง
2. publisher1 สื่อสารโดยใช้ topic1 โดยมี subscriber1_1 และ subscriber2_1
ให้ publisher1 ส่งข้อความผ่าน topic1
ฉะนั้น subscriber1_1 และ subscriber2_1 จะได้รับข้อความ แต่ subscriber3_1 ไม่ได้รับข้อความ
3. publisher2 สื่อสารโดยใช้ topic2 โดยมี subscriber3_2
ให้ publisher2 ส่งข้อความผ่าน topic2
ฉะนั้น subscriber3_1 จะได้รับข้อความ แต่ subscriber1_1 และ subscriber2_1 ไม่ได้รับข้อความ
Conclusion
จากผลที่ได้ สามารถบอกได้เลยว่า การทำ Pub/Sub ผ่าน Redis นั่น เป็นอะไรที่ง่ายและตรงไปตรงมามาก
การทำ Pub/Sub สามารถนำไปต่อยอด กับระบบต่าง ๆ ได้อีกมาก แต่ในบางกรณี อาจจะต้องการ Feature ที่มากกว่านี้ เช่น Push/Pull ที่ Redis ก็ทำได้ แต่จะแอบใช้งานยากหน่อย เป็นต้น
ตัว Redis Library เอง ก็ยังมี Feature อีกหลายอย่างที่ไม่ได้ นำมาใช้ใน Blog นี้