در برنامههای Real-Time با WebSocket، قطع اتصال (Disconnect) و نیاز به اتصال مجدد (Reconnection) یکی از چالشهای مهم است. مدیریت مناسب این شرایط باعث تجربه کاربری بهتر و افزایش پایداری سیستم میشود.
دلایل رایج قطع اتصال
- مشکلات شبکه یا کاهش پهنای باند
- Timeout سرور یا کلاینت
- حملههای شبکه یا قطع عمدی اتصال
- بروز خطا در پردازش پیامها در سرور یا کلاینت
روشهای پایدارسازی اتصال
- Heartbeat / Ping-Pong: ارسال پیامهای دورهای بین کلاینت و سرور برای بررسی سلامت اتصال.
- Retry با Backoff: در صورت قطع اتصال، کلاینت با تأخیرهای افزایشی (Exponential Backoff) تلاش به اتصال مجدد میکند.
- State Recovery: ذخیره وضعیت کلاینت و پیامهای در صف برای بازیابی پس از اتصال مجدد.
- Keep-Alive Timeout: محدود کردن زمان عدم فعالیت قبل از قطع اتصال برای جلوگیری از منابع بلااستفاده.
نمونه سرور FastAPI با Heartbeat
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
import asyncio
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
try:
# Timeout برای دریافت پیام
data = await asyncio.wait_for(websocket.receive_text(), timeout=30.0)
await websocket.send_text(f"Server received: {data}")
except asyncio.TimeoutError:
# ارسال پیام heartbeat
await websocket.send_text("ping")
except WebSocketDisconnect:
print("Client disconnected")
نمونه کلاینت پایتون با Reconnection و مدیریت Heartbeat
import asyncio
import websockets
uri = "ws://127.0.0.1:8000/ws"
async def websocket_client():
backoff = 1
while True:
try:
async with websockets.connect(uri) as websocket:
print("Connected to server")
backoff = 1 # Reset backoff after successful connection
while True:
message = input("Enter your message: ")
await websocket.send(message)
response = await websocket.recv()
if response == "ping":
print("Heartbeat received")
else:
print(f"Server response: {response}")
except (websockets.exceptions.ConnectionClosed, ConnectionRefusedError):
print(f"Connection lost. Reconnecting in {backoff} seconds...")
await asyncio.sleep(backoff)
backoff = min(backoff * 2, 30) # Exponential backoff
asyncio.run(websocket_client())
توضیح:
- در سرور، با استفاده از Timeout و پیامهای heartbeat سلامت اتصال بررسی میشود.
- کلاینت در صورت قطع اتصال با روش Exponential Backoff تلاش به اتصال مجدد میکند.
- این روش از فشار زیاد به سرور هنگام قطع اتصالهای مکرر جلوگیری میکند.
- حفظ state و بازیابی پیامهای از دست رفته در اتصال مجدد، به پایداری سیستم کمک میکند.