
قبل از اینکه درباره HTTP، WebSocket یا هر تکنولوژی دیگری صحبت کنیم، بهتر است اول خود «معماری ارتباط» را بشناسیم.
چون تفاوت اصلی سیستمها معمولاً نه در زبان برنامهنویسی است، نه در Framework؛ بلکه در مدلی است که برای ارتباط بین Client و Server انتخاب میکنند.
وقتی یک اپلیکیشن با سرور ارتباط برقرار میکند، چند سؤال بنیادی پشت صحنه وجود دارد:
چه کسی ارتباط را شروع میکند؟
ارتباط کوتاهمدت است یا دائمی؟
Server وضعیت Client را نگه میدارد یا نه؟
داده فقط هنگام درخواست ارسال میشود یا بهصورت لحظهای Push میشود؟
سیستم synchronous است یا asynchronous؟
پاسخ به همین سؤالهاست که معماری ارتباط را شکل میدهد.
اولین تفاوت مهم بین معماریهای ارتباطی این است که چه کسی شروعکننده ارتباط باشد.

در مدل Pull، این Client است که درخواست ارسال میکند و Server فقط در پاسخ به همان درخواست داده برمیگرداند.
Client ---> Request ---> Server Client <--- Response --- Server
این همان مدلی است که سالها پایه اصلی Web بوده است.
مثالها:
HTTP
REST APIs
Polling
مزیت اصلی این مدل، سادگی و مقیاسپذیری بالاست.
اما یک محدودیت مهم دارد:
Server نمیتواند خودش دادهای ارسال کند مگر اینکه Client درخواست جدیدی بفرستد.
به همین دلیل realtime کردن سیستمهایی مثل Chat یا Live Dashboard روی معماری Pull سختتر میشود.
در مدل Push، Server میتواند بدون درخواست جدید از سمت Client، داده را ارسال کند.
Server ---> Event/Data ---> Client
این مدل برای سیستمهای realtime طراحی شده است.
مثالها:
WebSocket
SSE
Firestore Realtime Listeners
در این معماری، Client معمولاً یک connection باز نگه میدارد و Server هر زمان event جدیدی رخ دهد، داده را Push میکند.
مزیت اصلی:
تاخیر (latency ) پایین
realtime واقعی
کاهش درخواستهای غیرضروری
اما در عوض:
مدیریت connection پیچیدهتر میشود
scaling سختتر میشود
Server باید state بیشتری نگه دارد
یکی از مهمترین تفاوتهای معماریهای ارتباطی، نحوه مدیریت state است.

در معماری Stateless، هر request مستقل از request قبلی است.
Server هیچ اطلاعاتی درباره ارتباط قبلی نگه نمیدارد.
Request #1 -> مستقل Request #2 -> مستقل Request #3 -> مستقل
مثال کلاسیک:
HTTP
REST APIs
مزیت بزرگ Stateless بودن:
Horizontal Scaling سادهتر
Load Balancing راحتتر
Fault tolerance بهتر
چون هر request میتواند توسط هر سروری پردازش شود.
به همین دلیل HTTP هنوز هم backbone بسیاری از سیستمهای اینترنتی است.
در معماری Stateful، Server وضعیت connection یا session را نگه میدارد.
Client <==== Persistent Connection ====> Server
مثالها:
WebSocket
Realtime Sync Engines
Multiplayer Game Servers
در این مدل، ارتباط فقط یک request ساده نیست؛
بلکه یک session دائمی بین Client و Server شکل میگیرد.
مزایا:
realtime communication
synchronization
bidirectional messaging
اما هزینههایی هم دارد:
memory usage بیشتر
scaling پیچیدهتر
مدیریت connection lifecycle
نیاز به distributed coordination
تمام ارتباطها قرار نیست فوری و همزمان باشند.

در این مدل Client درخواست ارسال میکند و تا دریافت پاسخ منتظر میماند.
Request ---> Wait ---> Response
این مدل ساده و قابلفهم است، اما برای عملیات سنگین یا طولانی مناسب نیست.
در معماری asynchronous، درخواست ثبت میشود اما پاسخ ممکن است بعداً پردازش شود.
Client -> Queue -> Worker -> Result
مثالها:
Message Queues
Kafka
RabbitMQ
Event Bus Architectures
این مدل در سیستمهای توزیعشده و scalable بسیار رایج است.
یکی دیگر از تفاوتهای مهم، طول عمر connection است.

ارتباط فقط برای یک request ایجاد میشود و بعد بسته میشود.
Connect -> Request -> Response -> Close
مثل HTTP سنتی.
ارتباط باز باقی میماند و چندین پیام روی همان connection ردوبدل میشود.
Connect ======================= Active
مثل:
WebSocket
SSE
HTTP/2 Streams
این مدل latency را کاهش میدهد و برای realtime communication مناسبتر است، اما مدیریت آن پیچیدهتر است.
در ادامه مقاله، تمام تکنولوژیهای ارتباطی را با همین مدل ذهنی بررسی میکنیم؛
چون بدون درک این مفاهیم، HTTP فقط یک request است و WebSocket فقط یک socket.
اما وقتی این تفاوتهای معماری روشن شوند، میتوان فهمید که هر روش دقیقاً چه مسئلهای را حل میکند و چه trade-off هایی به همراه دارد.
قبل از اینکه Web تبدیل به چیزی شبیه اپلیکیشنهای امروزی شود، اینترنت بر پایه یک مدل بسیار ساده ساخته شده بود:
Client ---> Request ---> Server Client <--- Response --- Server
Client درخواستی ارسال میکرد، Server پاسخ میداد و ارتباط تمام میشد. همین.
امروز این مدل آنقدر بدیهی بهنظر میرسد که شاید ساده و ابتدایی دیده شود، اما واقعیت این است که بخش بزرگی از موفقیت و رشد اینترنت، نتیجه همین سادگی بود.
HTTP بر پایه معماری Request/Response ساخته شده است.
یعنی:
Client همیشه شروعکننده ارتباط است
Server فقط در پاسخ به request عمل میکند
ارتباط معمولاً کوتاهمدت است
هر request مستقل از request قبلی است
مثلاً:
GET /products
یا:
POST /login
Server درخواست را پردازش میکند، response را برمیگرداند و connection بسته میشود.

یکی از مهمترین ویژگیهای معماری HTTP، Stateless بودن آن است.
یعنی Server بهصورت پیشفرض چیزی از request قبلی به خاطر نمیسپارد.
Request #1 -> مستقل Request #2 -> مستقل Request #3 -> مستقل
هر request باید تمام اطلاعات لازم برای پردازش را همراه خودش داشته باشد.
مثلاً:
authentication token
session id
headers
request data
همه باید در همان request ارسال شوند.
این تصمیم معماری، یکی از دلایل اصلی scalability اینترنت شد.
وقتی Server نیازی به نگهداری state نداشته باشد:
هر request میتواند توسط هر server پردازش شود
load balancing سادهتر میشود
horizontal scaling راحتتر میشود
failure recovery بهتر انجام میشود
مثلاً اگر ۱۰ server داشته باشیم:
Client Request ↓ Load Balancer ↙ ↓ ↘ S1 S2 S3
هر request میتواند به هر node ارسال شود بدون اینکه server قبلی مهم باشد.
و این دقیقاً همان چیزی بود که Web برای رشد massive خودش نیاز داشت.
HTTP یک معماری Pull-based است.
یعنی همیشه Client باید درخواست جدیدی ارسال کند تا داده دریافت کند.
Client ---> Request ---> Server
Server نمیتواند خودش ارتباط را شروع کند یا دادهای ارسال کند.
این موضوع در سالهای اولیه Web کاملاً منطقی بود، چون بیشتر صفحات فقط document بودند:
HTML page
image
form submission
اما بعدها همین ویژگی تبدیل به محدودیت شد.
سادگی HTTP یکی از بزرگترین نقاط قوت آن است.
تقریباً تمام زبانها و platformها از HTTP پشتیبانی میکنند.
به دلیل Stateless بودن، scaling سادهتر است.
HTTP برای caching طراحی بسیار خوبی دارد:
Cache-Control ETag Expires
و همین موضوع فشار روی server را کاهش میدهد.
تقریباً تمام زیرساخت اینترنت برای HTTP optimized شده است:
CDN
Reverse Proxy
Load Balancer
Browser
Firewall
با رشد Web، محدودیتهای این معماری کمکم مشخص شد.
بزرگترین مشکل HTTP این بود:
Server بدون request جدید از سمت Client نمیتواند دادهای ارسال کند.
مثلاً اگر پیام جدیدی در Chat برسد، Server راه مستقیمی برای اطلاع دادن به Client ندارد.
در مدل سنتی HTTP:
Connect -> Request -> Response -> Close
بعد از هر response ارتباط بسته میشود.
برای ارتباطهای مکرر، این موضوع overhead ایجاد میکند.
برای هر interaction جدید:
connection
request
response
دوباره تکرار میشود.
وقتی Web از «صفحههای ساده» به سمت «اپلیکیشنهای realtime» حرکت کرد، HTTP دیگر بهتنهایی کافی نبود.
نیازهای جدیدی به وجود آمد:
Chat
Notification
Live Dashboard
Multiplayer Systems
Streaming Data
اما معماری HTTP برای این نوع ارتباط طراحی نشده بود.
در نتیجه توسعهدهندهها شروع کردند به ساخت workaround هایی برای realtime communication.
اولین راهحل رایج: Polling بود؛
روشی ساده اما پرهزینه که تلاش میکرد محدودیت Pull-based بودن HTTP را دور بزند.
در Polling، کلاینت بهصورت مداوم و در بازههای زمانی مشخص، درخواست جدید ارسال میکند تا بررسی کند آیا داده جدیدی وجود دارد یا نه.
مثلاً:
Every 5 seconds: GET /notifications
یا:
Every 2 seconds: GET /messages
معماری کلی:
Client ---> Request ---> Server Client <--- Response --- Server (wait) Client ---> Request ---> Server Client <--- Response --- Server
در واقع Client دائماً میپرسد:
«چیزی تغییر کرده؟»

با اینکه هدف Polling ایجاد حس realtime است، اما از نظر معماری هنوز همان مدل Pull-based HTTP باقی میماند.
یعنی:
ارتباط همیشه توسط Client شروع میشود
Server همچنان passive است
connection کوتاهمدت باقی میماند
فقط تعداد requestها بیشتر شده است.
دلیل محبوب شدن Polling خیلی ساده بود:
پیادهسازی آن بسیار آسان بود.
بدون نیاز به:
protocol جدید
connection دائمی
infrastructure پیچیده
فقط کافی بود Client هر چند ثانیه یک request بفرستد.
به همین دلیل سالها در بسیاری از سیستمها استفاده میشد.
Polling هنوز هم در بعضی سناریوها منطقی است.
مثلاً:
بررسی وضعیت Jobها
سیستمهای ساده Notification
Admin Panels
Monitoring با حساسیت پایین
Synchronizationهای غیر realtime
اگر latency چندثانیهای قابلقبول باشد، Polling میتواند انتخاب ساده و مناسبی باشد.
مشکل اصلی Polling از جایی شروع میشود که scale بالا میرود.
فرض کنیم ۱۰۰ هزار Client داشته باشیم و هر Client هر ۵ ثانیه یک request ارسال کند.
100,000 clients × Request every 5s
حتی اگر هیچ داده جدیدی وجود نداشته باشد، Server همچنان باید requestها را پردازش کند.
یعنی بخش بزرگی از traffic کاملاً useless است.
در بسیاری از مواقع response چیزی شبیه این است:
{ "updates": [] }
یعنی:
request ارسال شده
connection باز شده
server پردازش انجام داده
ولی هیچ اتفاقی نیفتاده
این یعنی:
مصرف CPU
مصرف bandwidth
فشار روی infrastructure
بدون value واقعی.
هرچه interval کوتاهتر باشد:
Polling every 1 second
Realtime بهتر میشود، اما:
تعداد requestها افزایش پیدا میکند
هزینه infrastructure بالا میرود
فشار روی backend بیشتر میشود
و اگر interval را زیاد کنیم:
Polling every 30 seconds
هزینه کمتر میشود، اما realtime بودن تقریباً از بین میرود.
پس Polling همیشه بین این دو گیر میکند:
Lower Latency Higher Cost
Higher Latency Lower Cost
در HTTP سنتی، هر request معمولاً شامل:
TCP handshake
HTTP headers
authentication
request parsing
است.
وقتی requestها مدام تکرار شوند، این overhead بسیار noticeable میشود.
در مقیاس بالا، Polling میتواند backend را overload کند.
خصوصاً وقتی:
تعداد کاربران زیاد باشد
interval کوتاه باشد
responseها سنگین باشند
در چنین شرایطی، بخش بزرگی از منابع Server صرف بررسی requestهایی میشود که هیچ تغییر جدیدی ندارند.
Polling در واقع تلاشی بود برای شبیهسازی realtime روی معماریای که ذاتاً realtime نبود.
و همین موضوع باعث شد محدودیتهای آن خیلی زود مشخص شود.
توسعهدهندهها به دنبال راهی بودند که:
تعداد requestهای غیرضروری کمتر شود
latency کاهش پیدا کند
realtime طبیعیتر شود
اما هنوز نمیخواستند کاملاً از مدل HTTP خارج شوند.
نتیجه این تلاشها: Long Polling بود؛
مدلی که سعی میکرد Server را کمی «فعالتر» کند بدون اینکه معماری Web کاملاً تغییر کند.
Polling یک مشکل اساسی داشت:
Client مدام request ارسال میکرد، حتی وقتی هیچ داده جدیدی وجود نداشت.
این یعنی مقدار زیادی traffic و پردازش غیرضروری.
برای حل این مشکل، ایده جدیدی شکل گرفت:
«اگر Server بهجای پاسخ فوری، کمی صبر کند چه؟»
و این دقیقاً پایه Long Polling بود.
در Long Polling، Client درخواست ارسال میکند، اما اگر داده جدیدی وجود نداشته باشد، Server connection را باز نگه میدارد و فوراً پاسخ نمیدهد.
Client ---> Request ---> Server (wait...) Client <--- Response ---- Server
Server منتظر میماند تا:
event جدیدی اتفاق بیفتد
دادهای تغییر کند
یا timeout رخ دهد
و بعد response را ارسال میکند.

در Polling معمولی:
Request -> Immediate Response
حتی اگر data جدیدی وجود نداشته باشد.
اما در Long Polling:
Request -> Wait Until Update
این تفاوت ساده، تعداد زیادی از requestهای useless را حذف میکرد.
معمولاً روند به این شکل است:
1. Client sends request 2. Server waits 3. Event happens 4. Server responds 5. Client immediately reconnects
یعنی connection دائمی نیست، اما تقریباً همیشه یک request فعال وجود دارد.
تا حد زیادی بله.
چون بهمحض رخ دادن event، Server پاسخ را ارسال میکند.
Latency نسبت به Polling بسیار کمتر میشود.
چون برای اولین بار، Web را به چیزی نزدیک به realtime تبدیل کرد بدون اینکه نیاز به protocol جدیدی باشد.
همهچیز هنوز روی HTTP انجام میشد.
این موضوع در زمان خودش بسیار مهم بود، چون:
Browserها محدود بودند
Infrastructure برای WebSocket آماده نبود
Proxyها و Firewallها با HTTP راحتتر کار میکردند
سالها بسیاری از سیستمهای realtime اولیه از Long Polling استفاده میکردند:
Chat applications
Notification systems
Realtime feeds
Collaboration tools
حتی بعضی نسخههای اولیه:
Facebook Chat
Gmail updates
Slack
تا مدتها از مدلهایی شبیه Long Polling استفاده میکردند.
بزرگترین مزیت آن نسبت به Polling همین بود.
Server میتوانست بهمحض وقوع event پاسخ بدهد.
بدون نیاز به protocol جدید.
با:
Browserها
Proxyها
Firewallها
CDNها
سازگارتر از بسیاری از راهحلهای realtime اولیه بود.
Long Polling نسبت به Polling بهتر بود، اما هنوز محدودیتهای مهمی داشت.
در HTTP سنتی، connectionها کوتاهمدت بودند.
اما حالا Server باید هزاران connection باز را نگه میداشت:
10,000 waiting connections
و این از نظر resource management ارزان نبود.
هر connection باز:
memory مصرف میکند
file descriptor مصرف میکند
resource نگه میدارد
در scale بالا، این موضوع به bottleneck تبدیل میشود.
بعد از هر response:
Response -> Reconnect -> Wait Again
Client باید دوباره request جدید بفرستد.
یعنی هنوز:
reconnect وجود دارد
headers تکرار میشوند
HTTP overhead باقی میماند
Long Polling هنوز ذاتاً:
request/response
client-driven
است.
Server فقط زمانی میتواند data ارسال کند که request فعالی وجود داشته باشد.
Long Polling یک مرحله transitional بود.
نه کاملاً realtime،
نه کاملاً traditional HTTP.
بلکه تلاشی برای نزدیک کردن معماری Request/Response به event-driven communication.
نیاز به ارتباطی وجود داشت که:
دائمی باشد
overhead کمتری داشته باشد
bidirectional باشد
reconnect مداوم نداشته باشد
واقعاً realtime باشد
و اینجا بود که Web کمکم به سمت: Persistent Connections حرکت کرد.
اولین قدم مهم در این مسیر: Server-Sent Events (SSE) بود؛
مدلی ساده و lightweight که برای اولین بار اجازه میداد Server بهصورت واقعی داده را به Client push کند.
تا اینجا تمام مدلهایی که دیدیم، هنوز یک ویژگی مشترک داشتند:
ارتباط همیشه توسط Client شروع میشد.
حتی در Long Polling هم Server فقط زمانی میتوانست داده ارسال کند که یک request فعال از سمت Client وجود داشته باشد.
اما کمکم Web به سمت سیستمهایی حرکت کرد که نیاز داشتند Server بتواند مستقیماً و لحظهای داده ارسال کند:
Live notifications
Monitoring dashboards
News feeds
Streaming updates
AI response streaming
و اینجا بود که معماری: Server-Sent Events (SSE) شکل گرفت.
در SSE، Client یک request HTTP ارسال میکند، اما برخلاف HTTP معمولی، connection باز باقی میماند.
Client ---> Connection ---> Server Client <--- Stream of Events ---
بعد از برقراری connection، Server میتواند هر زمان event جدیدی رخ دهد، داده را به Client ارسال کند.
SSE یک معماری:
Push-based
Persistent
Server-to-Client Streaming
است.
یعنی:
connection دائمی است
Server فعالانه data ارسال میکند
Client فقط listener است
در Polling:
Client: "چیزی تغییر کرده؟"
اما در SSE:
Server: "این هم update جدید."
یعنی برای اولین بار، Web واقعاً push-based شد.
روند معمول به این شکل است:
1. Client opens connection 2. Connection stays alive 3. Server pushes events continuously 4. Client receives updates instantly
بدون reconnect مداوم،
بدون polling،
بدون requestهای تکراری.
Client:
const events = new EventSource('/events'); events.onmessage = (event) => { console.log(event.data); };
Server:
data: New notification data: User joined data: Price updated
Server عملاً یک stream دائمی از eventها ارسال میکند.
چون نسبت به Long Polling:
سادهتر بود
latency پایینتری داشت
overhead کمتری داشت
realtime طبیعیتری ایجاد میکرد
بدون اینکه complexity کامل WebSocket را وارد سیستم کند.
SSE روی HTTP معمولی کار میکند.
نیازی به protocol جدید ندارد.
Server میتواند بدون request جدید data ارسال کند.
برخلاف Polling، reconnect مداوم وجود ندارد.
SSE برای data stream بسیار مناسب است.
مثلاً:
AI response streaming
Live feeds
Metrics
Notifications
چون SSE هنوز مبتنی بر HTTP است:
proxyها
firewallها
load balancerها
معمولاً راحتتر با آن کار میکنند.
با وجود مزایا، SSE هنوز محدودیتهای مهمی داشت.
SSE فقط:
Server ---> Client
است.
Client نمیتواند روی همان connection data ارسال کند.
اگر Client بخواهد چیزی بفرستد، هنوز باید HTTP request جداگانه ارسال کند.
SSE اساساً text-based است.
برای binary streaming مناسب نیست.
در بعضی browserها تعداد connectionهای همزمان محدود بود و SSE میتوانست به bottleneck تبدیل شود.
هر connection باز:
memory مصرف میکند
resource نگه میدارد
lifecycle دارد
پس scaling همچنان سختتر از HTTP سنتی است.
SSE برای سناریوهایی عالی است که:
ارتباط mostly one-way باشد
server بیشتر producer باشد
client فقط consumer باشد
مثلاً:
Live notifications
Activity feeds
Monitoring dashboards
Realtime analytics
AI token streaming
Stock tickers
وقتی پاسخ ChatGPT کمکم stream میشود:
Hello... How are...
این دقیقاً مدلی شبیه SSE است.
Server بهصورت incremental داده را push میکند.
SSE اولین معماری mainstream در Web بود که:
واقعاً push-based شد
streaming واقعی ارائه داد
persistent connection داشت
اما هنوز یک محدودیت بزرگ باقی مانده بود:
ارتباط فقط یکطرفه بود.
Web کمکم به سمت اپلیکیشنهایی حرکت میکرد که نیاز داشتند:
Client و Server همزمان data ارسال کنند
latency بسیار پایین باشد
ارتباط کاملاً realtime باشد
و اینجا بود که Web وارد دنیای: WebSocket شد؛
معماریای که ارتباط بین Client و Server را از Request/Response به یک connection دائمی و bidirectional تبدیل کرد.
تا قبل از WebSocket، Web هنوز تا حد زیادی بر پایه مدل سنتی Request/Response حرکت میکرد.
حتی SSE با وجود realtime بودن، هنوز یک محدودیت مهم داشت:
ارتباط فقط از سمت Server به Client بود.
اما نسل جدید اپلیکیشنها به چیزی فراتر نیاز داشتند:
Chat applications
Online gaming
Live collaboration
Trading systems
Multiplayer apps
سیستمهایی که در آنها:
Client و Server باید همزمان داده ارسال کنند
latency باید بسیار پایین باشد
ارتباط باید دائمی و realtime باشد
و اینجا بود که معماری: WebSocket متولد شد.
WebSocket ارتباط بین Client و Server را از مدل Request/Response به یک connection دائمی و دوطرفه تبدیل میکند.
Client <=======> Server
بعد از برقراری connection:
هر دو سمت میتوانند هر زمان data ارسال کنند
connection باز باقی میماند
نیازی به reconnect مداوم نیست
نکته جالب اینجاست که WebSocket معمولاً با یک HTTP request شروع میشود.
Upgrade: websocket Connection: Upgrade
بعد از handshake اولیه، ارتباط از HTTP خارج میشود و وارد protocol مخصوص WebSocket میشود.
از این لحظه دیگر خبری از:
request
response
polling
reconnect مداوم
نیست.
WebSocket یک معماری:
Persistent
Stateful
Bidirectional
Full-Duplex
است.
یعنی:
connection دائمی است
هر دو سمت active هستند
data میتواند همزمان در هر دو جهت حرکت کند

در HTTP:
Request -> Response -> Close
اما در WebSocket:
connect ================= Active Stream
connection تبدیل به یک channel دائمی میشود.
چون برای اولین بار Web توانست رفتاری شبیه applicationهای desktop یا network protocolهای realtime پیدا کند.
یعنی:
latency بسیار پایین
realtime واقعی
event-driven communication
bidirectional messaging
Client:
const socket = new WebSocket('ws://server'); socket.onmessage = (event) => { console.log(event.data); }; socket.send('Hello');
اینجا:
Server میتواند هر زمان message ارسال کند
Client هم هر زمان بخواهد data میفرستد
بدون request جدید.
تاخیر بسیار پایین است.
هر دو سمت میتوانند producer و consumer باشند.
دیگر برای هر message:
HTTP headers
reconnect
handshake
تکرار نمیشود.
WebSocket ذاتاً event-oriented است.
WebSocket برای سیستمهایی مناسب است که:
ارتباط دائمی نیاز دارند
latency بسیار مهم است
تبادل data دوطرفه است
مثل:
Chat systems
Multiplayer games
Collaborative editors
Trading platforms
Live dashboards
Presence systems
Realtime notifications
و این دقیقاً جایی است که معماری اهمیت پیدا میکند.
بسیاری از تیمها فقط به realtime بودن WebSocket نگاه میکنند، اما complexity معماری آن را نادیده میگیرند.
برخلاف HTTP، حالا Server باید connectionها را نگه دارد.
100,000 active sockets
هر connection:
memory مصرف میکند
lifecycle دارد
باید مدیریت شود
در HTTP هر request مستقل بود.
اما حالا:
Client A -> Server 1 Client B -> Server 2
اگر Client A پیامی بفرستد و Client B روی node دیگری باشد، سیستم باید somehow message را بین serverها synchronize کند.
اینجاست که سیستمها وارد دنیای:
Redis Pub/Sub
Kafka
NATS
Message Brokers
میشوند.
در HTTP:
هر request میتواند به هر server برود
اما در WebSocket:
connection دائمی است
server state نگه میدارد
پس Load Balancer باید:
sticky session داشته باشد
connection-aware باشد
حالا باید این مسائل مدیریت شوند:
reconnect
heartbeat
timeout
dead connections
network interruption
و این complexity کمی نیست.
در HTTP tracing سادهتر است چون requestها مستقلاند.
اما در WebSocket:
event stream طولانی داریم
state دائماً تغییر میکند
debugging سختتر میشود
یکی از اشتباههای رایج این است که:
«هر realtimeای = WebSocket»
در حالی که بسیاری از سیستمها اصلاً به bidirectional communication نیاز ندارند.
مثلاً:
Notification stream
AI output streaming
Live metrics
ممکن است با SSE سادهتر و scalableتر حل شوند.
WebSocket نقطهای بود که Web از مدل سنتی document-based فاصله گرفت و به سمت application-level communication حرکت کرد.
اما complexity آن هم به همان اندازه افزایش پیدا کرد.
در واقع WebSocket فقط یک protocol نیست؛
ورود به دنیای:
stateful systems
distributed coordination
realtime infrastructure
است.
با رشد سیستمهای توزیعشده، کمکم مشخص شد که realtime communication تنها مسئله نیست.
سیستمها نیاز داشتند:
سرویسها با هم سریعتر صحبت کنند
streaming داخلی داشته باشند
communication typed و efficient باشد
latency بین serviceها کمتر شود
و اینجا بود که معماریهای جدیدتری مثل: gRPC و بعد از آن:
Event Streaming
Message Queues
Realtime Sync Engines
وارد معماری سیستمهای مدرن شدند.
مسیر تکامل Web را میتوان تا حد زیادی از زاویه «معماری ارتباط» نگاه کرد.
در ابتدا، Web بر پایه مدل ساده و قدرتمند HTTP Request/Response ساخته شد؛
مدلی stateless، scalable و مناسب برای دنیایی که بیشتر از document و page تشکیل شده بود.
اما با تبدیل شدن Web به یک platform برای applicationهای interactive، محدودیتهای این معماری کمکم آشکار شد.
نیازهای جدیدی به وجود آمد:
realtime communication
live updates
low latency interactions
bidirectional messaging
persistent synchronization
و هرکدام از معماریهایی که بررسی کردیم، در واقع پاسخی به همین نیازها بودند.
Polling تلاش کرد realtime را روی HTTP شبیهسازی کند، اما به قیمت requestهای مکرر و مصرف بالای resource.
Long Polling قدمی به جلو بود و توانست ارتباط را طبیعیتر و کمهزینهتر کند، اما هنوز در چارچوب Request/Response باقی مانده بود.
SSE برای اولین بار مفهوم واقعی Push-based communication را وارد Web کرد و امکان streaming ساده و lightweight را فراهم ساخت.
و در نهایت، WebSocket ارتباط بین Client و Server را از یک مدل سنتی مبتنی بر request، به یک connection دائمی، realtime و bidirectional تبدیل کرد.
اما نکته مهم اینجاست که هیچکدام از این معماریها «بهترین» نیستند.
هر مدل ارتباطی، مجموعهای از trade-off ها را به همراه دارد.
معمولاً هرچه:
realtime بیشتر شود،
latency کمتر شود،
و synchronization قویتر شود،
complexity سیستم هم افزایش پیدا میکند.

به همین دلیل انتخاب معماری ارتباط، فقط یک تصمیم تکنیکال نیست؛
بلکه یک تصمیم معماری است که مستقیماً روی:
scalability
infrastructure
maintainability
observability
operational cost
developer experience
تأثیر میگذارد.
یکی از اشتباههای رایج در طراحی سیستمها این است که تکنولوژیها صرفاً بر اساس trend یا hype انتخاب شوند.
در حالی که در بسیاری از پروژهها:
HTTP کاملاً کافی است،
Polling هنوز منطقی است،
یا SSE انتخاب سادهتر و مناسبتری نسبت به WebSocket محسوب میشود.
Realtime بودن همیشه ارزش complexity بیشتر را ندارد.
در نهایت، معماری ارتباط فقط درباره انتقال data نیست؛
بلکه درباره نحوه فکر کردن به interaction بین اجزای سیستم است.
اینکه:
چه کسی کنترل ارتباط را در دست دارد،
state کجا نگهداری میشود،
ارتباط چگونه scale میشود،
و سیستم تا چه اندازه باید realtime، resilient و distributed باشد.
و دقیقاً همین تصمیمها هستند که تفاوت بین یک API ساده و یک سیستم realtime در مقیاس بزرگ را مشخص میکنند.
در مقاله بعدی، از دنیای ارتباطات Web فراتر میرویم و سراغ معماری ارتباط در سیستمهای توزیعشده مدرن میرویم؛
جایی که مفاهیمی مثل:
gRPC
Event Streaming
Kafka
Message Queues
Realtime Synchronization
Distributed Messaging
نقش اصلی را بازی میکنند.