Come correggere errori di Discourse Forum /message-bus o Long Polling

1. Problema

Quando Discourse è configurato con una CDN, si verifica un errore comune:

/message-bus/204234de907442e8b77e153786a58e5b/poll
Connessione fallita / timeout / codice di stato anomalo

Impatto:

  • Notifiche fallite: Il punto rosso (nuovo PM/risposta) non appare più in tempo reale; gli aggiornamenti potrebbero arrivare in ritardo o non arrivare affatto.

  • Aggiornamenti in tempo reale interrotti: Nuovi post/like/voti non si aggiornano automaticamente; è necessario un aggiornamento manuale della pagina.

  • Esperienza utente degradata: Appaiono messaggi di “Connessione persa”; le interazioni sono lente.

  • Aumento del carico del server: Il frontend continua a ritentare i sondaggi, aumentando la pressione sull’origine.

Motivo: Discourse utilizza il long polling per mantenere la comunicazione in tempo reale. Molte CDN applicano la memorizzazione nella cache predefinita, timeout abbreviati, controlli di sfida/firewall o buffering su connessioni lunghe, causando interruzioni o risposte memorizzate nella cache che interrompono il comportamento in tempo reale.


2. Approccio Generale (Stabilità Prima di Tutto)

  • Separazione dei domini: Instrada MessageBus attraverso un dominio dedicato che si connette direttamente all’origine.

  • Livello di reverse proxy (Nginx):

    • Abilita CORS per /message-bus.
    • Disabilita il buffering del proxy, rilassa i timeout, vieta esplicitamente la memorizzazione nella cache.
  • Livello CDN (se ancora utilizzato):

    • Configura /message-bus/* con nessuna memorizzazione nella cache, timeout esteso, nessuna sfida JS/CAPTCHA/rate limiting e passaggio di cookie/autorizzazione.
    • Oppure bypassa completamente la CDN.

3. Passaggi di Implementazione

1) Configura le Variabili d’Ambiente di Discourse

Modifica app.yml (solitamente in /var/discourse/containers/app.yml) e aggiungi/modifica sotto env::

env:
  DISCOURSE_MESSAGE_BUS_REDIS_ENABLED: true
  DISCOURSE_LONG_POLLING_BASE_URL: "https://messagebus.example.com"

Applica le modifiche (distribuzione ufficiale):

cd /var/discourse
./launcher rebuild app

Spiegazione:

  • DISCOURSE_LONG_POLLING_BASE_URL indica al frontend di utilizzare il dominio MessageBus.
  • REDIS_ENABLED dovrebbe rimanere abilitato.

2) DNS e Certificato

  • Punta messagebus.example.com direttamente all’origine, bypassando la CDN (best practice).
  • Imposta un certificato HTTPS valido per il dominio.

3) Nginx (Dominio MessageBus) Reverse Proxy e CORS

Aggiungi o aggiorna quanto segue nel blocco server per messagebus.example.com:

location ^~ /message-bus {

    # (1) Gestisci il preflight CORS (OPTIONS)
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' 'https://bbs.example.com' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,discourse-deferred-track-view-topic-id,discourse-present,discourse-track-view,discourse-deferred-track-view,x-silence-logger,dont-chunk,x-shared-session-key' always;
        add_header 'Access-Control-Max-Age' 1728000 always;
        add_header 'Content-Type' 'text/plain; charset=UTF-8' always;
        add_header 'Content-Length' 0 always;
        return 204;
    }

    # (2) Reverse proxy a Discourse
    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    # o, se standalone:
    # proxy_pass http://127.0.0.1:3000;

    # (3) Impedisci intestazioni CORS duplicate
    proxy_hide_header Access-Control-Allow-Origin;
    proxy_hide_header Access-Control-Allow-Credentials;
    proxy_hide_header Access-Control-Allow-Methods;
    proxy_hide_header Access-Control-Allow-Headers;
    proxy_hide_header Access-Control-Max-Age;

    # (4) CORS normale per le richieste
    add_header 'Access-Control-Allow-Origin' 'https://bbs.example.com' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,discourse-deferred-track-view-topic-id,discourse-present,discourse-track-view,discourse-deferred-track-view,x-silence-logger,dont-chunk,x-shared-session-key' always;

    # (5) Impostazioni di stabilità per il long polling
    proxy_read_timeout    120s;
    proxy_send_timeout    120s;
    proxy_connect_timeout 60s;

    proxy_buffering off;
    add_header X-Accel-Buffering no always;

    # (6) Vieta esplicitamente la memorizzazione nella cache
    add_header Cache-Control "no-store, no-cache, must-revalidate" always;
}

:warning: Nota di sicurezza: Se viene utilizzato Access-Control-Allow-Credentials: true, Origin non deve essere *; deve corrispondere al dominio esatto del forum.


4) Regole CDN (se il forum è ancora dietro CDN)

Consigliato: imposta nessuna cache + timeout esteso + bypass WAF/rate limiting per questi percorsi:

Esempio di espressione regolare:

^/(session|login|message-bus|admin|u|users)(/|$)

Politica:

  • Nessuna memorizzazione nella cache del browser/nodo (no-store/no-cache).
  • Timeout upstream/lettura/idle ≥ 60–120s.
  • Disabilita sfide JS/CAPTCHA/gestione bot.
  • Passa attraverso cookie e intestazioni di autorizzazione (non rimuovere).

4. Come Verificare il Successo

1) Strumenti per Sviluppatori del Browser → Rete

Nella pagina del forum:

  • Osserva /message-bus/…/poll.
  • La richiesta dovrebbe “bloccarsi” per circa 20–60 secondi, quindi restituire 200 (possibilmente vuoto).
  • La richiesta di sondaggio successiva viene attivata automaticamente.

Controlla le intestazioni di risposta:

  • Access-Control-Allow-Origin: https://bbs.example.com
  • Cache-Control: no-store
  • Nessun Age, X-Cache: HIT o CF-Cache-Status: HIT (significa che non è memorizzato nella cache).

Problemi comuni:

  • Errori fissi di 10s/30s → timeout del margine/origine.
  • 504/524: timeout.
  • 499: disconnessione del livello intermedio.
  • 403/401: blocco WAF/autenticazione.

2) Sonda Rapida da Riga di Comando (opzionale)

Verifica la connettività e le intestazioni (non il polling completo):

curl -I "https://messagebus.example.com/message-bus/health-check" \
  -H "Origin: https://bbs.example.com"

Nota: i sondaggi effettivi richiedono il contesto della sessione; questo verifica solo CORS e la connettività.

1 Mi Piace