بعضی برنامه‌ها پیام را فقط از سرور به مرورگر می‌فرستند. SSE یا Server-Sent Events این کار را روی HTTP انجام می‌دهد؛ برخلاف WebSocket به upgrade نیاز ندارد. امشب زمان رسیدن هر پیام را اندازه می‌گیریم.

این جلسه بخشی از دورهٔ آپاچی در ۵۰ شب است. قرارداد نام‌ها، مسیرها و روش اعمال تغییر را در راهنمای دوره بخوان.

محیط: app، Python 3، backend تازه روی 8082؛ نگاشت‌های خاص قبل از / قرار می‌گیرند.

جریان کوچک و قابل مشاهده#

فایل ~/apache-lab/events.py:

import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

class Events(BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "text/event-stream")
        self.send_header("Cache-Control", "no-cache")
        self.send_header("Connection", "close")
        self.end_headers()
        try:
            for n in range(5):
                self.wfile.write(f"data: lab-{n}\n\n".encode())
                self.wfile.flush()
                time.sleep(2)
        except (BrokenPipeError, ConnectionResetError):
            pass
        self.close_connection = True

ThreadingHTTPServer(("127.0.0.1", 8082), Events).serve_forever()

برنامه را اجرا کن؛ این نمونه برای بهره‌برداری عمومی نیست. در app:

ProxyPass /events/ http://127.0.0.1:8082/ timeout=15
ProxyPassReverse /events/ http://127.0.0.1:8082/
<Location /events/>
    SetEnv no-gzip 1
</Location>

برای SetEnv ماژول env لازم است. فشرده‌سازی و لایه‌های cache ممکن است مشاهدهٔ پیام را به تأخیر بیندازند؛ مسیر streaming را مستقل بررسی کن.

curl -N --http1.1 --cacert ~/apache-lab/pki/ca.crt \
  --resolve app.example.test:443:192.168.56.10 https://app.example.test/events/

-N بافر خروجی curl را خاموش می‌کند. باید پنج پیام تقریباً با فاصلهٔ دو ثانیه ببینی، نه همه در پایان. مستقیم روی loopback و سپس با --http2 هم اندازه بگیر تا محل تأخیر مشخص شود.

اتصال بیکار و ظرفیت#

timeout خواندن backend با زمان کل عمر جریان یکی نیست. heartbeat برنامه و timeout لایه‌های میانی باید هماهنگ باشند. افزایش عمومی timeout برای همهٔ مسیرها می‌تواند منابع را درگیر کند؛ نیاز مسیر streaming را جدا تعیین کن.

تمرین و بازگشت: فاصلهٔ پیام‌ها را از timeout بیشتر کن و قطع ارتباط را در لاگ مشاهده کن. پس از آزمون، فاصله را برگردان، config مسیر events را حذف و backend را متوقف کن.

منبع: SSE در MDN ، timeoutهای proxy .