আমার development journey শুরু হয়েছিল PHP দিয়ে। আর স্বাভাবিকভাবেই জানেন যে PHP দিয়ে data fetch করাতে হলে প্রত্যেক বার HTTP request করতে হতো। তখন আমি first time Facebook-এর messenger-এর chatting feature দেখে অবাক হয়েছিলাম। কোনো reload ছাড়াই message send এবং receive হচ্ছে।
এই বিষয় টা নিয়ে একটু research করার পরে জানতে পারি এইটা asynchronous communication। Page reload ছাড়াই server request পাঠানো যায়। এইটা মূলত করা HTTP request দিয়ে, যেমন এখন আমরা fetch বা axios দিয়ে করি।
কিন্তু problem হচ্ছে, page reload ছাড়া অপর সাইডে message receive হয় না। একটু বিস্তারিত বলি, মনে করুন আপনি আপনার friend-কে message দিলেন, এখন এই http বা axios দিয়ে server-এ message দিলেন। এখন আপনার friend যতক্ষণ না তার page reload করছে ততক্ষণ এই message receive হবে না।
কিন্তু আমি যেটা দেখেছিলাম, সেটা কিন্তু সম্পূর্ণ achieve করা হয়নি। Just ৫০% achieve হয়েছে মাত্র। এই জন্য আরেকটু research করি। তখন জানতে পারি আমি এতক্ষণ যেটা try করছিলাম, সেটা হচ্ছে ১-way communication কিন্তু আমাদের দরকার ২-way communication। এটা নিয়ে deep dive করলে জানতে পারি যে ২-way communication-এর জন্য WebSocket use করা হয়। আর WebSocket real-time-এ communicate করতে পারে। Reload করা ছাড়াও message send এবং receive করা যায়।
WebSocket কী?
WebSocket হলো একটা communication-এর method যেখানে server এবং client always connected থাকে। এই connection close হয় না। Typical HTTP request-এ client-এর কিছু দরকার হলে, server-এ request পাঠায় তখন connection start হয়, data receive হয়ে গেলে এই connection close হয়ে যায়। কিন্তু WebSocket-এ এই connection-টা close হয় না। Always connected থাকে।
WebSocket-এর use case ওপরের কথাতেই বুঝে যাওয়ার কথা। এ ছাড়াও আরও অনেক use case আছে।
WebSocket-এর সমস্যা
মনে করুন, একটা গেমের leaderboard। এখানে কোন player-এর position কত সেটা live দেখাবে। এখানে যে দেখবে, সে হচ্ছে client। এখন আপনার কাছে প্রশ্ন, "Client তো শুধু দেখছে, সে আর input দিচ্ছে না। তাহলে এখানে যদি WebSocket use করি তাহলে কি ভালো হবে?"
উত্তর দেওয়ার আগে একটা জিনিস বোঝার চেষ্টা করি। WebSocket ২-way communication-এর জন্য use হয়। কিন্তু এখানে লাগছে ১-way। Server শুধু data push করবে। Client end থেকে data push করার দরকার নেই। তাহলে এখানে WebSocket use করলে কিছু waste হবে। Resource-এর proper use হবে না। তাহলে মোদ্দা কথা হচ্ছে, WebSocket ideal solution না। তাহলে solution-টা কী?
Solution-এ যাওয়ার আগে, এই টাইপের real-time communication-এর জন্য অনেকগুলো method আছে।
Real Time Communication Methods
Short Polling
এই method-এ, একটা সময় (short time) পর পর server-এ request পাঠিয়েই যাবে এবং data update করবে। নিচের example-টা দেখুন:
setInterval(async () => {
const data = await fetch("/api/messages");
}, 2000); // প্রতি ২ সেকেন্ডে
এখানে প্রতি ২ সেকেন্ড পর পর server-এ request পাঠাচ্ছে কোনো message আছে কিনা। এই method-টা ভালোই তবে এখানে কিছু problem আছে। যেমন, যদি server-এ নতুন কোনো message আসেনি, তাহলে কি request করার দরকার আছে? নেই। কিন্তু এই method-এ এটা হবে। Server-এ নতুন কোনো message আছে কিনা তা নিয়ে এই method-এর কোনো মাথাব্যথা নেই। এই method-এ request প্রতি ২ সেকেন্ড পর পর যেতেই থাকবে। এখন এই unnecessary request-এর জন্য server-এ load বাড়বে + bandwidth-ও নষ্ট হবে। বিষয়টা মনে হতে পারে খুব একটা problematic না। কিন্তু যখন user ১ মিলিয়নে চলে যাবে তখন এই ২ সেকেন্ডের unnecessary request আপনার server down হওয়ার main reason হবে।
Long Polling: একটু চালাক
Long Polling, Short Polling-এর থেকে একটু চালাক। Short Polling তো interval পর পর request দিচ্ছে। কিন্তু Long Polling-এ server বলে, "তুমি আমার কাছে request দাও, দিয়ে তুমি wait করো, যখনই নতুন data আসবে তখন আমি তোমাকে response করব। তারপর তুমি যা খুশি করো।" নিচের example দেখুন:
async function poll() {
const data = await fetch("/api/messages/wait"); // Server hold করে রাখে
process(data);
poll(); // আবার শুরু
}
এটা Short Polling-এর problem কিছুটা solve করলেও নতুন problem নিয়ে আসে। যেমন, এই method server connection close করে না। আর close না করলে সেই connection-এর data RAM-এ store করে রাখে। এখন আপনার system concurrently ১০০০ user request handle করতে পারে। কিন্তু worst case-এ এই ১০০০ user-ই একই সাথে request করল। তখন কী হবে? আপনার server-এর memory শেষ, এর মানে পুরা server crash করবে। এ ছাড়াও client side-এও problem তৈরি হওয়ার possibility আছে।
এটাকে অনেকটা real-time-এর মতো মনে হলেও technically ওই simple HTTP-কেই একটু logic দিয়ে use করা হচ্ছে। বিষয়টা অনেকটা এই রকম—খেজুরের রস জ্বাল দিয়ে গুড় তৈরি করা।
WebSockets: Two-way Communication
WebSocket জিনিসটা কী সেটা তো already বুঝেই গেছেন। WebSocket HTTP protocol use করে না বললেই চলে। WebSocket communication-এ TCP protocol use করে। WebSocket শুধুমাত্র connection-এর জন্য একদম প্রথমে HTTP request send করে। Connection হয়ে গেলে WebSocket TCP-এর মাধ্যমে data transfer করে থাকে। নিচের example-টা দেখুন:
// Server
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", (ws) => {
ws.on("message", (message) => {
// সবাইকে broadcast
wss.clients.forEach((client) => client.send(message));
});
});
// Client
const ws = new WebSocket("ws://localhost:8080");
ws.onmessage = (event) => console.log(event.data);
ws.send("Hello!");
WebSocket জিনিসটা বাকিগুলোর থেকে একটু complex, reason-টা বুঝেই গেছেন। বাকিগুলোতে ১-way communication হয় আর এখানে ২-way communication।
কখন WebSocket ব্যবহার করবেন
- Chat application
- Multiplayer game
- Collaborative editing (Google Docs)
- Live trading platform
Server-Sent Events (SSE): One-way Push
একটা ছোট question করি, আমার যদি শুধু ১-way communication লাগে—মানে এখানে server শুধু input দিবে বা নতুন data show করাবে real-time-এ, কিন্তু user-এর দিক থেকে কোনো input-এর দরকার হবে না, তখন কি WebSocket use করাটা ভালো হবে? ওপরে ঠিক এই টাইপের একটা problem-এর কথা বলেছিলাম।
এই problem-টা address করার জন্য আসে Server-Sent Events (SSE)। এই method-এ server client-এ data push করে আর client সেই data receive করে থাকে। Server-এ যখনই কোনো নতুন data আসে তখন server নতুন data-কে stream করে দেয় আর client সেটা receive করে use করে। নিচের example-টা দেখুন:
// Server (NestJS)
@Sse('events')
sendEvents(): Observable<MessageEvent> {
return interval(1000).pipe(
map(() => ({ data: { time: new Date().toISOString() } }))
);
}
// Client
const source = new EventSource('/api/events');
source.onmessage = (event) => console.log(event.data);
কখন SSE ব্যবহার করবেন
- Live notifications
- News feed
- Progress updates
- Stock prices
এখন ওপরে যে problem-টার কথা বলেছিলাম, আপনার মতে কোন method-টা use করলে better হবে?
সংক্ষেপে কোনটা কখন?
| পরিস্থিতি | Solution |
|---|---|
| Simple notification | SSE |
| Chat, game | WebSocket |
| Legacy system | Long Polling |
| Simple polling OK | Short Polling |
Real Life Example
সিনারিও:
একটি ব্লগের আর্কিটেকচারের কথা চিন্তা করুন।
ইউজার ফ্রন্টএন্ডে একটি নতুন পোস্ট তৈরি করল। এই সিস্টেমে ব্যবহার করা হয়েছে CQRS Pattern। ফ্লো-টি কিছুটা এমন: Frontend -> Post Service -> Write DB-তে Insert -> Kafka-তে Event Publish
এর পর Query Service ওই Event রিসিভ করে Read DB-তে পোস্টটি সেভ করে।
যেহেতু Read এবং Write-এর জন্য দুটো আলাদা সার্ভিস ও ডাটাবেস কাজ করছে, তাই ডাটা দুটো ডাটাবেসে সিঙ্ক (Sync) হতে কিছুটা সময় লাগে।
এখন ফ্রন্টএন্ডে ইউজার পোস্ট ক্রিয়েট করার পর পরই যদি হোম পেজে গিয়ে সব পোস্ট ফেচ করতে চায়, তবে সিঙ্ক হতে সময় লাগার কারণে পুরানো ডাটা বা স্টেল ডাটা চলে আসতে পারে, তাই না?
প্রশ্ন হলো: রিয়েল-টাইমে লেটেস্ট ডাটা পাওয়ার জন্য এবং রিয়েল-টাইমে সব ইউজারের হোম পেজে সেই পোস্ট দেখানোর জন্য ফ্রন্টএন্ডে কীভাবে হ্যান্ডেল করবেন? আপনার সলিউশন কী—WebSocket নাকি অন্য কিছু?
সলিউশন:
এই সিনারিওতে:
- Long Polling: বিবেচনা করা যাবে না, কারণ ডাটা একদম রিয়েল-টাইমে দেখাতে হবে।
- Short Polling: অযথা একের পর এক অনর্থক API কল করে সার্ভারে লোড বাড়াবে।
- WebSocket: এখানে Overkill । কারণ WebSocket Bidirectional যোগাযোগের জন্য ব্যবহৃত হয়। কিন্তু আমাদের সিনারিওতে ফ্রন্টএন্ডের কাজ শুধু সার্ভার থেকে রিয়েল-টাইমে ডাটা রিসিভ করা, ক্লায়েন্ট থেকে ব্যাকগ্রাউন্ডে কিছু পাঠানোর দরকার নেই।
- Server-Sent Events (SSE): এটাই হলো সবচেয়ে সেরা অপশন! এই মেথডে সার্ভার প্রয়োজন অনুযায়ী রিয়েল-টাইমে ফ্রন্টএন্ডে ডাটা পুশ করবে আর ফ্রন্টএন্ড শুধু ডাটা রিসিভ করে স্ক্রিনে দেখাবে।
- অপশন ১: write database-এ ডাটা ইনসার্ট হওয়ার সাথে সাথেই SSE-এর মাধ্যমে ফ্রন্টএন্ডে ডাটা পুশ করে দেওয়া।
- অপশন ২: write database-এ ডাটা sync হওয়া পর্যন্ত অপেক্ষা করা, তারপর ফ্রন্টএন্ডে ডাটা পাঠানো।
_(বি: দ্র: আমরা চাইলে Optimistic Way-তেও ডাটা পাঠাতে পারি, তবে সেক্ষেত্রে একটা Rollback Mechanism রাখতে হবে।)_
বটম লাইন
Real-time-এর জন্য WebSocket বা SSE mandatory কিছু না। কোনটা use করতে হবে সেটা totally depend করবে আপনার application কী চাচ্ছে। Requirement-এর ওপর depend করেই decision নিতে হবে। এমনও case আছে যেখানে Short Polling-টাই best solution। For example, Log Aggregations করার ক্ষেত্রে। আপনি ২৪ ঘণ্টার interval দিয়ে log aggregate করতে পারেন। ওই situation-এ Short Polling সেরা perform করবে। তাই আপনার requirement কী সেটা আগে ঠিক করুন, তারপর decision নিন।
আপনার প্রজেক্টে কোনটা ব্যবহার করেছেন? কোনো Challenge ছিল? কমেন্টে শেয়ার করুন! 👇