sgcWebSockets 2026.7: clustering, cronologia dei messaggi, async / await e client irrobustiti | Blog eSeGeCe

sgcWebSockets 2026.7: clustering, cronologia dei messaggi, async / await e client irrobustiti

· Versioni

sgcWebSockets 2026.7 parla di produzione. Ora puoi distribuire un'applicazione WebSocket su più server e mantenere funzionanti canali, pub/sub e presence su tutti quanti. I canali possono ricordare i loro messaggi recenti, così un client che cade e torna riceve tutto ciò che si è perso. I client si riconnettono con backoff esponenziale e jitter invece di martellare il server all'unisono, la coda di invio può essere limitata perché un solo consumatore lento non esaurisca la memoria del server, e il client HTTP ha guadagnato una serie di protezioni contro i redirect che disperdono le credenziali, il TLS declassato e le risposte senza limite di dimensione.

Oltre a questo ci sono un livello async / await per Delphi, gzip e deflate sui server HTTP, il nuovo metodo HTTP QUERY, la verifica dell'identità per la cifratura end-to-end, OAuth2 sul client MCP e un lungo elenco di correzioni. Questo articolo è la visita guidata. Ogni sezione rimanda all'articolo che approfondisce la funzionalità.

Clustering su più server

Il nuovo componente TsgcWSCluster collega più server sgcWebSockets in un unico server logico. Un messaggio pubblicato sul nodo A raggiunge i sottoscrittori connessi al nodo B, e la presence restituisce l'elenco dell'intero cluster invece del solo nodo locale. Sono disponibili due backplane: una mesh integrata, in cui i nodi dialogano direttamente tra loro e non devi installare nulla di aggiuntivo, e Redis Pub/Sub per i deployment più grandi (Enterprise).

uses
  sgcWebSocket, sgcWebSocket_Protocols, sgcWebSocket_Cluster;

oCluster := TsgcWSCluster.Create(nil);
oCluster.EngineType  := clusterMesh;          // no extra infrastructure
oCluster.ClusterPort := 5410;                 // this node's mesh listener
oCluster.Peers.Add('192.168.1.101:5410');     // the other nodes
oCluster.Attach(oProtocol);                   // cluster this protocol's pub/sub
oCluster.Start;

Approfondisci: Scalare i server WebSocket su più nodi.

Cronologia dei messaggi e recupero alla riconnessione

Il server del protocollo sgc ora può conservare gli ultimi N messaggi di ogni canale, con un tempo di vita opzionale. Quando un client si riconnette e si risottoscrive, invia l'offset dell'ultimo messaggio che ha realmente visto, e il server riesegue tutto ciò che è stato pubblicato mentre era assente. Nel tuo codice client non cambia nulla oltre alla risottoscrizione che già fai, e l'intero meccanismo resta spento finché non lo abiliti.

oProtocol.History.Enabled    := True;
oProtocol.History.Size       := 1000;   // last 1000 messages per channel
oProtocol.History.TTLSeconds := 3600;   // optional: also expire after 1 hour

Approfondisci: Cronologia dei messaggi e recupero alla riconnessione.

async / await, e una Connect che aspetta davvero

La nuova unit sgcBase_AsyncAwait porta task e future nella libreria. Puoi attendere una richiesta HTTP, una connessione WebSocket o una chat completion AI senza collegare un solo gestore di eventi, concatenare il risultato con ThenProc e OnError, e annullare un task in modo che la richiesta sottostante venga davvero interrotta.

Nello stesso spirito, Connect ora blocca finché la connessione non è completamente stabilita, non semplicemente avviata, e Disconnect attende finché il socket non è davvero chiuso. Questo chiude una race condition che dava fastidio durante le riconnessioni rapide. Quando una connessione o un invio falliscono, il motivo è disponibile nella nuova proprietà LastError, e c'è un overload di Connect che ti restituisce direttamente la stringa di errore, così puoi diagnosticare un fallimento senza sottoscriverti a OnError.

var
  vError: string;
begin
  if sgcWebSocketClient1.Connect(10000) then
    sgcWebSocketClient1.WriteData('hello')
  else
    ShowMessage('Connect failed: ' + sgcWebSocketClient1.LastError);

  // or get the reason back directly from the call
  if not sgcWebSocketClient1.Connect(vError, 10000) then
    ShowMessage('Connect failed: ' + vError);
end;

Approfondisci: async / await in Delphi.

Irrobustire il client HTTP

Un redirect è il modo più facile per perdere un token. Se un server risponde a una tua richiesta autenticata con un 302 verso un host diverso, il client vi ripete allegramente gli header Authorization e Cookie. La 2026.7 aggiunge StripAuthOnCrossHostRedirect per rimuoverli su un redirect cross-site e NoInsecureRedirect per rifiutare un redirect che declassa HTTPS a HTTP in chiaro.

Ora anche le risposte possono essere limitate, con MaxChunkSize per un singolo pezzo di una risposta chunked e MaxResponseSize per il totale. RejectPublicSuffixCookies scarta i cookie dichiarati per domini eccessivamente ampi come "com" o "co.uk". Per gli upload c'è Expect: 100-continue, che chiede il permesso al server prima di inviare un body di grandi dimensioni, e un body di richiesta chunked per inviare in streaming un upload di cui non conosci ancora la dimensione.

oHTTP.StripAuthOnCrossHostRedirect := True;
oHTTP.NoInsecureRedirect           := True;
oHTTP.MaxResponseSize              := 10 * 1024 * 1024;  // 10 MB, 0 = unlimited
oHTTP.MaxChunkSize                 := 1024 * 1024;       // 1 MB per chunk
oHTTP.RejectPublicSuffixCookies    := True;

Tutti questi interruttori sono disattivati per impostazione predefinita, e nessuno di essi richiede di scendere all'oggetto HTTP di basso livello: sono pubblicati anche sui client API già pronti (AI/LLM, exchange crypto, OAuth2, Google Cloud, WhatsApp, AWS SQS, WebPush). Le protezioni su redirect e dimensioni sono presenti anche sul client HTTP/2, e HTTP/3 guadagna il limite sulla dimensione della risposta. Approfondisci: Irrobustire il client HTTP.

Retry, backoff e jitter

Il WatchDog si riconnetteva a intervalli fissi, il che significa che mille client che perdono il server tornano tutti nello stesso istante. Ora supporta il backoff esponenziale con un moltiplicatore, un tetto massimo e un jitter casuale, così la flotta si distribuisce nel tempo. L'intervallo fisso resta il valore predefinito, quindi non cambia nulla finché non lo richiedi.

Il client HTTP ha guadagnato una propria policy di retry: riprova su un elenco configurabile di status code, attende più a lungo ogni volta e rispetta il suggerimento Retry-After del server quando lo invia. Lo usano anche i client OpenAI, Anthropic e Gemini.

sgcWebSocketClient1.WatchDog.Backoff           := wdbExponential;
sgcWebSocketClient1.WatchDog.BackoffMultiplier := 2.0;   // double every attempt
sgcWebSocketClient1.WatchDog.MaxInterval       := 60;    // seconds, the ceiling
sgcWebSocketClient1.WatchDog.Jitter            := 0.2;   // up to 20% random spread

Approfondisci: Backoff esponenziale, jitter e Retry-After.

Backpressure sulla coda di invio

Quando un client legge più lentamente di quanto tu scriva, i messaggi in coda si accumulano nella memoria del server. Ora puoi limitare il numero di messaggi in attesa per connessione con QueueOptions.MaxQueueSize e scegliere cosa succede quando il limite viene raggiunto: scartare il messaggio più vecchio, scartare quello più recente, oppure disconnettere la connessione. Il nuovo evento OnSendBufferFull scatta prima che qualcosa venga scartato, così puoi registrarlo a log, contarlo, oppure impedire lo scarto per una connessione che non puoi permetterti di troncare. La coda è illimitata per impostazione predefinita.

oServer.QueueOptions.MaxQueueSize   := 1000;
oServer.QueueOptions.OverflowPolicy := qopDropOldest;  // or qopDropNewest, qopDisconnect

Approfondisci: Limiti della coda di invio per i client WebSocket lenti.

gzip e deflate sul server HTTP

I server HTTP ora possono comprimere le loro risposte ogni volta che il client dichiara Accept-Encoding. Vale per i file serviti da DocumentRoot e per le risposte che costruisci tu in OnCommandGet, salta i body sotto una dimensione minima e i content type che non diventerebbero più piccoli, ed è disponibile anche sul server HTTP.sys. La compressione è disattivata per impostazione predefinita, e per ora vengono compresse solo le risposte HTTP/1.1.

sgcWebSocketHTTPServer1.HTTPCompression.Enabled := True;
sgcWebSocketHTTPServer1.HTTPCompression.Level   := 6;     // 1..9
sgcWebSocketHTTPServer1.HTTPCompression.MinSize := 1024;  // bytes

Approfondisci: Compressione gzip e deflate sul server HTTP.

Il metodo HTTP QUERY

QUERY è un nuovo metodo HTTP dell'IETF che invia una ricerca nel body della richiesta come una POST, ma resta sicuro e memorizzabile in cache come una GET, così la tua interrogazione non deve più essere compressa in una URL con un limite di lunghezza. La 2026.7 lo implementa sui client HTTP/1.x, HTTP/2, HTTP/3 e REST, e i server e il proxy lo gestiscono.

vResult := oClient.Query('https://api.example.org/contacts', oQuery);

Approfondisci: Il nuovo metodo HTTP QUERY in Delphi.

Verifica dell'identità E2EE

La cifratura end-to-end mantiene privato il payload, ma da sola non ti dice chi c'è dall'altra parte. Un server o un relay nel mezzo può consegnare a ciascun lato una propria chiave e leggere tutto. Nella 2026.7 ogni lato può firmare la propria chiave di cifratura con una chiave di identità di lungo periodo, e l'altro lato verifica quella firma, così una sostituzione silenziosa della chiave viene rilevata invece che accettata.

Funziona per le conversazioni uno a uno e per le chat di gruppo, aggiunge eventi per approvare o fissare l'identità di un peer e per avvisarti quando la chiave di identità di un peer cambia, ed è disattivata per impostazione predefinita e pienamente compatibile con i peer 2026.6.

E2EE.E2EE_Options.Identity.Enabled    := True;
E2EE.E2EE_Options.Identity.PrivateKey := LoadIdentityPrivateKey;  // PEM
E2EE.E2EE_Options.Identity.PublicKey  := LoadIdentityPublicKey;   // PEM
E2EE.OnE2EEVerifyPeerIdentity := OnE2EEVerifyPeerIdentityEvent;
E2EE.OnE2EEKeyChange          := OnE2EEKeyChangeEvent;

Approfondisci: Verifica dell'identità E2EE.

OAuth2 per il client MCP e il grant Identity Assertion

Il client MCP ora può autenticarsi con OAuth2 invece che con una API key statica. Ottiene il token da solo, lo tiene in cache finché non scade e lo rinnova, e quando OAuth2 è abilitato ha la priorità sulla API key. Accanto a questo, il client OAuth2 guadagna un nuovo tipo di grant, l'Identity Assertion Authorization Grant, che concatena un'identità da un dominio a un altro: il client esegue per te l'intero scambio a più passi e solleva eventi così puoi seguire ogni passaggio.

MCPClient.MCPOptions.AuthenticationOptions.OAuth2.Enabled := True;
MCPClient.MCPOptions.AuthenticationOptions.OAuth2.GrantType := auth2ClientCredentials;
MCPClient.MCPOptions.AuthenticationOptions.OAuth2.TokenURL := 'https://auth.example.com/oauth2/token';
MCPClient.MCPOptions.AuthenticationOptions.OAuth2.ClientId := 'YOUR_CLIENT_ID';
MCPClient.MCPOptions.AuthenticationOptions.OAuth2.ClientSecret := 'YOUR_CLIENT_SECRET';

Approfondisci: OAuth2 per il client MCP.

Feed crypto: risottoscrizione e rate limiting

Fino ad ora, quando un socket di dati di mercato cadeva e il WatchDog lo riportava su, il socket era attivo ma tu non eri iscritto a nulla finché non rieseguivi tu stesso ogni sottoscrizione. Ora i client degli exchange possono farlo per te: imposta Resubscribe := True e i tuoi stream vengono ripristinati dopo una riconnessione. Copre Binance, Kraken, Coinbase e altri quattordici exchange circa, oltre al feed basato su sessione di XTB. È False per impostazione predefinita.

I client REST API guadagnano un rate limiter lato client opzionale, così una raffica di richieste non ti fa bandire temporaneamente da un exchange. Limita quante richieste invii in una finestra temporale e scegli se una richiesta in eccesso attende o viene rifiutata. Disattivato per impostazione predefinita.

oBinance.RateLimit.Enabled     := True;
oBinance.RateLimit.IntervalMs  := 60000;   // one minute window
oBinance.RateLimit.MaxRequests := 1000;
oBinance.RateLimit.Behavior    := rlbWait;

Approfondisci: Risottoscrizione e rate limiter lato client.

Aggiunte minori

Correzioni e irrobustimento

La 2026.7 porta con sé un lungo elenco di correzioni. Invece di ripeterle tutte, ecco a cosa si riducono nel complesso.

Sicurezza della memoria e irrobustimento dei parser. Sono state corrette letture oltre la fine del buffer nel client MQTT 5 (un broker che dichiara più dati di quanti ne abbia inviati), nel client AMQP 1.0 (decodifica degli UUID), nel parser STUN/TURN (compresi un ciclo infinito e gli indirizzi IPv6), nel data channel SCTP di WebRTC e nello scanner di frame TCP grezzo. Il client e il server UDP, DTLS incluso, non liberano più due volte un socket né lo lasciano pendente alla disconnessione. Sono stati introdotti limiti interni dove un peer malfunzionante avrebbe potuto altrimenti far crescere la memoria senza limiti: la coda dei messaggi in attesa di MQTT, le sottoscrizioni per connessione del protocollo sgc, le chiamate in attesa del server WAMP, le righe di trailer di una risposta chunked e la profondità di annidamento delle field table AMQP.

HTTP/2. Un limite sulla dimensione decompressa (64 MB per impostazione predefinita) chiude un buco di esaurimento della memoria con le risposte "zip bomb", il limite sulla dimensione della risposta non può più essere aggirato dall'ultima parte di una risposta, e una richiesta fallita ora fallisce subito invece di attendere l'intero timeout.

Crittografia e casualità. Il server WebAuthn, l'authorization server OAuth2 e gli id di sessione HTTP integrati ora usano un generatore di numeri casuali crittograficamente sicuro, le challenge sono monouso, e i segreti vengono confrontati in tempo costante (client secret, firma JWT, password Basic delle HTTP API). Un JWT con una firma valida ma un claim errato ora viene rifiutato invece che accettato. Con StrictVerify abilitato su OpenSSL, il certificato viene verificato anche rispetto al nome host, quindi un certificato valido ma emesso per un host diverso viene rifiutato. Le connessioni verso un indirizzo IP e le impostazioni esistenti non sono interessate.

Server-Sent Events. Una risposta in streaming che consegnava diversi eventi in una sola lettura, o un evento diviso su due letture, perdeva tutto tranne il primo. Il problema è risolto, e questo ripristina lo streaming token per token dei client AI/LLM. Anche la chat in streaming di OpenAI non impostava il flag di stream, quindi ora effettua lo streaming come gli altri provider.

Client degli exchange. Gli id di richiesta di Kraken ora sono strettamente crescenti, BitMEX invia la sua scadenza in secondi invece che in millisecondi, MEXC firma i parametri codificati che invia realmente, Cryptorobotics non scambia più due valori nelle chiamate by-hash, Deribit rinnova il token di login prima che scada, e il client Forex segnala l'errore che prima ingoiava durante la lettura dell'id dell'account.

Lazarus e Free Pascal. Tre correzioni di compilazione: le interfacce della unit JSON ora usano la calling convention giusta per ogni piattaforma (non compilavano su Linux), il client Forex non chiama più una funzione disponibile solo in Delphi per leggere il formato dei numeri, e la unit dello scambio di chiavi post-quantum non dipende più da size_t.

C'è dell'altro in history.txt, incluso il client gRPC (chiamate concorrenti potevano ricevere le risposte l'una dell'altra, e un invio fallito veniva riportato come riuscito), il server OpenAPI (il caricamento della spec ora è thread-safe e i tuoi handler non vengono più eseguiti mentre un lock interno è trattenuto), una perdita di connessione e di socket sul server a ogni login fallito, un crash sulle risposte OpenAI prive del campo "message" come quelle di Ollama e LM Studio, un WriteAndWaitData corretto sul client WinHTTP, e l'oscuramento dei segreti nel log del client HTTP, così abilitare il logging non scrive più i token su disco in chiaro.

L'edizione .NET

sgcWebSockets .NET 2026.7 si concentra sul client HTTP. Include lo stesso insieme di protezioni dell'edizione Delphi: rimozione delle credenziali su un redirect cross-site, blocco del declassamento da HTTPS a HTTP, limiti di dimensione per chunk e totali sulla risposta, rifiuto dei cookie su public suffix, Expect: 100-continue e body di richiesta chunked. Sono disponibili sui componenti client HTTP e sui client API già pronti (i client AI/LLM, OAuth2, Google Cloud, WhatsApp, AWS SQS, WebPush), e le stesse protezioni su redirect e dimensioni sono presenti sul client HTTP/2. Sono incluse anche le correzioni alla gestione dei redirect e alla scadenza dei cookie. Tutto è disattivato per impostazione predefinita.

Aggiornamento

La 2026.7 è un aggiornamento immediato per i progetti 2026.x esistenti. Ogni nuova funzionalità di questa release è disattivata per impostazione predefinita: clustering, cronologia dei messaggi, backoff, limite della coda di invio, compressione HTTP, protezioni del client, verifica dell'identità E2EE e risottoscrizione degli exchange vanno tutti attivati esplicitamente, quindi installare la nuova build non modifica alcun comportamento finché non scegli di abilitarli.

I clienti con un abbonamento attivo possono scaricare la nuova build dall'area clienti, oppure da esegece.com/products/websockets/download.

Domande, commenti o aiuto per la migrazione? Contattaci. Riceverai una risposta dalle persone che hanno scritto il codice.