O sgcWebSockets 2026.5 é uma versão robusta. Três novos componentes de infraestrutura transformam o servidor WebSocket / HTTP em um gateway de API de nível de produção: um rate limiter completo, um circuit breaker no lado do cliente e um gerenciador de chaves de API com suporte completo ao ciclo de vida. No lado dos protocolos há um novo cliente Forex.com construído sobre uma implementação genérica de Lightstreamer TLCP 2.5, o MCP Server ganha um fluxo OAuth 2.1 embutido para que possa se conectar diretamente a clientes MCP baseados em navegador como o claude.ai, e os motores de E/S IOCP (Windows) e EPOLL (Linux) recebem seis ganhos de desempenho mensuráveis. Há também uma primitiva pós-quântica inicial: sgcKEM_CreateMLKEM768Keys para geração de pares de chaves ML-KEM-768.
Este post apresenta os destaques com trechos de Delphi prontos para colar para os novos componentes.
TsgcWSRateLimiter — limitação de taxa de API pronta para uso
Coloque um TsgcWSRateLimiter ao lado do seu servidor e você terá limitação de taxa por token-bucket, janela deslizante ou janela fixa por IP, por chave de API, por usuário ou por padrão de endpoint, além de cotas diárias/mensais e proteção contra rajadas. O componente é thread-safe e persiste o estado em disco (assim, uma reinicialização do servidor não concede a cada cliente uma nova cota).
uses
sgcWebSocket_Server_RateLimiter;
var
oRL: TsgcWSRateLimiter;
oResult: TsgcRateLimitResult;
begin
oRL := TsgcWSRateLimiter.Create(nil);
try
oRL.TokenBucket.Enabled := True;
oRL.TokenBucket.Capacity := 100; // burst size
oRL.TokenBucket.RefillRate := 10; // tokens / interval
oRL.TokenBucket.RefillIntervalMs := 1000;
oRL.PerIP.Enabled := True;
oRL.PerIP.MaxRequests := 60;
oRL.PerIP.WindowSec := 60;
// Consume one token for the current request
oResult := oRL.Consume('ip:' + vClientIP);
if not oResult.Allowed then
RespondHTTP(429, 'Retry-After: ' + IntToStr(oResult.RetryAfterSec));
finally
oRL.Free;
end;
end;
O resolvedor de regras percorre PerEndpoint (com correspondência por curinga), depois PerAPIKey, PerUser e, por fim, PerIP. Os eventos OnThrottled, OnQuotaExceeded e OnStateChange permitem registrar ou sobrescrever cada decisão.
Demonstração: Demos\04.WebSocket_Other_Samples\14.RateLimiter — executa um cliente gerador de inundação contra um servidor que publica estatísticas em tempo real e motivos de rejeição.
TsgcWSCircuitBreaker — isolamento de falhas no lado do cliente
Quando uma API upstream (api.openai.com, um gateway de pagamentos, um microsserviço interno) começa a falhar ou ficar lenta, ficar pendurado em timeouts de TCP custa conexões, threads e dinheiro. O TsgcWSCircuitBreaker implementa o clássico padrão de três estados (fechado / aberto / semiaberto) em cima de qualquer subclasse de TsgcHTTPAPI_client, com janela de tempo deslizante, detecção de chamadas lentas, respostas de fallback opcionais e substituições por endpoint.
uses
sgcWebSocket_CircuitBreaker;
var
oCB: TsgcWSCircuitBreaker;
begin
oCB := TsgcWSCircuitBreaker.Create(nil);
try
oCB.Thresholds.FailureCount := 5;
oCB.Thresholds.FailureRatePercent := 50;
oCB.Thresholds.SlowCallDurationMs := 2000;
oCB.Thresholds.SlowCallRatePercent := 80;
oCB.TimeWindow.RollingWindowSec := 60;
oCB.Recovery.CooldownSec := 30;
oCB.Recovery.HalfOpenTrialCalls := 3;
oCB.Fallback.Enabled := True;
oCB.Fallback.UseLastSuccess := True;
if oCB.IsCallAllowed('openai') then
try
vResponse := oOpenAI.ChatCompletion(...);
oCB.RecordSuccess('openai');
except
on E: Exception do
begin
oCB.RecordFailure('openai', E.ClassName);
raise;
end;
end
else
vResponse := 'service temporarily unavailable';
finally
oCB.Free;
end;
end;
No Delphi 2009+ também está disponível um wrapper de uma linha: oCB.Execute('openai', procedure begin oOpenAI.ChatCompletion(...) end); — o registro de sucesso / falha acontece automaticamente.
Demonstração: Demos\04.WebSocket_Other_Samples\15.CircuitBreaker.
TsgcWSAPIKeyManager — ciclo de vida de chaves em um único componente
A maioria dos servidores de "API WebSocket" precisa de chaves de API: emitir, validar, revogar, rotacionar. O TsgcWSAPIKeyManager envolve todo o ciclo de vida com autorização baseada em escopo, hashing opcional em repouso, expiração, um log de auditoria e um período de carência de rotação embutido para que as chaves antigas continuem funcionando por uma janela configurável após a rotação.
uses
sgcWebSocket_Server_APIKeyManager;
var
oKM: TsgcWSAPIKeyManager;
vKey, vNewKey: string;
begin
oKM := TsgcWSAPIKeyManager.Create(nil);
try
oKM.Generation.Length := 40;
oKM.Generation.Prefix := 'sgc_';
oKM.Hashing.Enabled := True; // store SHA-256 hash, not the plaintext
oKM.Rotation.GracePeriodSec := 86400; // old key valid for 24h after rotation
oKM.Expiration.DefaultTTLSec := 30 * 86400;
// Issue a key for tenant "acme" with read+write scopes, expiring in 7 days
vKey := oKM.IssueKey('acme', ['read', 'write'], 7 * 86400);
// Validate the key on each request, optionally requiring a scope
if not oKM.ValidateKey(vKey, 'read', vClientIP) then
RespondHTTP(401, 'invalid api key');
// Rotate a key (returns the new plaintext; old key remains valid for GracePeriodSec)
oKM.RotateKey(vKey, vNewKey);
finally
oKM.Free;
end;
end;
O componente pode ler a chave diretamente dos cabeçalhos HTTP de entrada ou da query string com IsRequestAuthorized, de modo que você não precisa cuidar da extração por conta própria.
Demonstração: Demos\04.WebSocket_Other_Samples\16.APIKeyManager.
Cliente Forex.com + Lightstreamer genérico
O novo cliente TsgcWSAPI_Forex oferece acesso unificado REST + streaming ao Forex.com (login, ping, monitoramento de mercado, posições, ordens, histórico de operações, simulação de operação). Ele é construído sobre um novo componente TsgcWSPClient_Lightstreamer, um cliente Lightstreamer TLCP 2.5 genérico que implementa create_session, bind_session, control (subscribe / unsubscribe) e o auto-rebind LOOP + replay de inscrições após reconexão. O cliente Lightstreamer é reutilizável por si só, portanto a mesma base de código funciona com IG Markets e qualquer outro feed apoiado por Lightstreamer.
uses sgcHTTP_API_Forex;
var oFX: TsgcWSAPI_Forex;
begin
oFX := TsgcWSAPI_Forex.Create(nil);
oFX.UserName := 'demo-user';
oFX.Password := 'secret';
oFX.AppKey := 'your-app-key';
oFX.Login;
oFX.SubscribePrices(['EUR/USD', 'GBP/USD', 'XAU/USD']);
oFX.OnPriceUpdate := procedure(const aSymbol: string; aBid, aAsk: Double)
begin
ShowMessage(Format('%s %.5f / %.5f', [aSymbol, aBid, aAsk]));
end;
end;
Uma demonstração completa com GUI está em Demos\05.Crypto\22.Forex — login, ping de conectividade, monitoramento de mercado ao vivo, posições, ordens ativas, histórico de operações, histórico de stop / limit e simulação de operação, com credenciais persistidas em sgcForexDemo.ini.
MCP Server — OAuth 2.1 para clientes MCP baseados em navegador
O MCP Server agora pode se comunicar diretamente com conectores MCP baseados em navegador (como o claude.ai) sem um servidor de autorização externo. Ele publica automaticamente os quatro endpoints de descoberta / registro OAuth exigidos pela especificação de conector de navegador do MCP, executa um fluxo de autorização PKCE-S256 com uma tela de consentimento em HTML e emite refresh tokens:
GET /.well-known/oauth-authorization-server— metadados RFC 8414.GET /.well-known/oauth-protected-resource— metadados de recurso protegido RFC 9728.POST /oauth/register— registro dinâmico de cliente RFC 7591.GET /oauth/authorize— formulário de consentimento em HTML.POST /oauth/token— PKCE S256 + refresh tokens.
CORS é tratado inline: o preflight OPTIONS retorna 204 com cabeçalhos Access-Control-* completos antes da autenticação, cada resposta carrega um Access-Control-Allow-Origin refletindo a origem da requisição e um cabeçalho HSTS Strict-Transport-Security: max-age=31536000.
IOCP e EPOLL: seis ganhos de ajuste
Os motores de E/S IOCP no Windows e EPOLL no Linux receberam uma rodada focada de trabalho em desempenho e ajustabilidade.
IOCP (Windows)
ThreadAffinity(padrãoFalse) emTsgcIndy_IO_Engine— fixa as threads do motor em round-robin nos núcleos lógicos viaSetThreadAffinityMask. Reduz o tráfego de cache entre núcleos em sistemas com muitos núcleos.Metrics— um novo registroTsgcIndy_IO_EngineMetrics(AcceptsPosted,AcceptsCompleted,ReadsPosted,ReadsCompleted,ActiveConnections,BytesRead,BytesWritten) atualizado sob uma seção crítica. Sem mais adivinhação.SendBufferSize,ReceiveBufferSize,TCPNoDelayemTsgcIndy_IOHandler_IO_IOCP— aplicados emAfterAcceptviasetsockopt, então o ajuste por conexão não exige mais um handlerOnConnectpersonalizado.TsgcPerIoDataPoolteve sua capacidade elevada de 256 para 2048, evitando o fallback de heap viaGetMem/FreeMemsob alta concorrência de conexões. +15–18% de throughput de WebSocket em benchmarks de loopback.
oServer.Bindings.Add.Port := 443;
oServer.IOHandler := TsgcIndy_IOHandler_IO_IOCP.Create(oServer);
with TsgcIndy_IOHandler_IO_IOCP(oServer.IOHandler) do
begin
SendBufferSize := 256 * 1024;
ReceiveBufferSize := 256 * 1024;
TCPNoDelay := True;
Engine.ThreadAffinity := True;
end;
EPOLL (Linux)
AcceptBatchSize,WaitTimeoutMS,HandshakeTimeoutMS— ajustam o loop de accept e a proteção contra slow-loris.- Backpressure de escrita orientada por EPOLLOUT — quando
send()retornaEAGAINem uma escrita parcial, os bytes restantes são capturados em um buffer pendente por conexão e o socket é rearmado comEPOLLIN|EPOLLOUT. O reator descarrega o restante no próximo eventoEPOLLOUTem vez de descartar os bytes ou bloquear o worker.
Compartilhado
O pool de workers do IOCP / EPOLL costumava executar sleep(1) a cada iteração inclusive logo após uma tarefa ser processada — efetivamente limitando cada worker a ~1.000 ops/s mesmo quando a fila estava cheia. O sleep agora é ignorado enquanto há trabalho aguardando, removendo o limite.
HTTP.sys: modo de alto desempenho opt-in
O servidor HTTP.sys ganha uma propriedade FineTune com um seletor OperatingMode. O padrão ompClassic preserva o comportamento existente. O novo modo ompHighPerf implementa o padrão MSDN de N workers × M recebimentos assíncronos pré-postados — a arquitetura recomendada para implantações HTTP.sys de alto throughput — por trás de uma única propriedade:
oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.HTTP2Options.SecureOptions.HTTPAPI := True; // use HTTP.sys
oServer.FineTune.OperatingMode := ompHighPerf;
oServer.FineTune.WorkerCount := 8;
oServer.FineTune.PrePostedReceivesPerWorker := 16;
oServer.Active := True;
THttpServerRequest e THttpServerResponse também foram estendidos com campos adicionais que cobrem detalhes anteriormente disponíveis apenas por meio de parsing manual.
Primitiva pós-quântica: ML-KEM-768
Uma adição pequena, porém voltada para o futuro: sgcKEM_CreateMLKEM768Keys gera um par de chaves ML-KEM-768 (FIPS 203 / Kyber-768) tanto em formato PEM quanto em bytes brutos. ML-KEM é o KEM pós-quântico padronizado pelo NIST e no roteiro do IETF para TLS 1.3 híbrido (X25519MLKEM768). Isso destrava a experimentação com handshakes prontos para PQ antes do próximo baseline OpenSSL 3.5 / 3.6.
uses sgcKEM;
var vPubPEM, vPrivPEM: string; vPubRaw, vPrivRaw: TBytes;
begin
sgcKEM_CreateMLKEM768Keys(vPubPEM, vPrivPEM, vPubRaw, vPrivRaw);
TFile.WriteAllText('mlkem768_pub.pem', vPubPEM);
TFile.WriteAllText('mlkem768_priv.pem', vPrivPEM);
end;
Correções de confiabilidade e conformidade
O lote de correções de bugs fecha uma longa lista de problemas em MCP, HTTP.sys, IOCP e HTTP/2. Destaques:
- MCP Server — credenciais ausentes ou inválidas agora retornam
401 Unauthorizedcom um cabeçalhoWWW-Authenticate: Bearerapontando para os metadados do recurso protegido, em vez de500 Internal Server Error. Necessário para descoberta OAuth por clientes MCP baseados em navegador. - MCP Server — requisições
OPTIONSnão atingem mais o parser JSON-RPC (antes retornavam500 "Invalid jsonrpc Value"). O preflight de CORS agora é tratado antes da autenticação e antes do parser de corpo MCP. - MCP Server — descrições de ferramentas, mensagens de prompt e conteúdos de recursos contendo caracteres não-ASCII não quebram mais a conexão (o corpo JSON agora corresponde ao
charset=utf-8declarado). - MCP Server — campos
namedetool/prompt/resource/root/template/ completion-ref e completion-argument contendo caracteres não-ASCII agora são corretamente emitidos e lidos como escapes JSON\uXXXXem vez de pontos de código UTF-16 brutos. - Corpo de requisição HTTP API —
TsgcWSComponent_Server.DoHTTPRequestAPIcostumava chamarReadStringFromStreamsem especificar uma codificação, recorrendo a ASCII por padrão e substituindo cada byte não-ASCII por?antes que os handlers de evento o vissem. Corrigido. - HTTP.sys Server — vazamento de contexto em
ERROR_MORE_DATAemTsgcHTTPServerAPI.DoExecute. O loop de accept agora aumenta o buffer e tenta novamenteHttpReceiveHttpRequestno mesmo request id, e libera contextos órfãos em todos os caminhos de erro. - HTTP.sys Server —
TsgcWSConnectionServer_HTTPAPI.DoSendHTTP_Responsenão define maisHTTP_SEND_RESPONSE_FLAG_MORE_DATAna resposta final. - IOCP IOHandler —
TsgcIndy_IO_Engine_IOCP_Base.DoStopThreadsestava chamandoWaitForMultipleObjectsem um array de IDs de threadDWORD(FThreadsId) em vez de HANDLEs de thread. Corrigido. - IOCP IOHandler — operações de E/S pendentes em sockets agora são canceladas no shutdown e no fechamento por socket.
- IOCP IOHandler — a frágil verificação
Overlapped.Internal = STATUS_PENDINGemDoFreePerIoDatafoi substituída por uma flag explícitaCompleted: BooleanemTsgcPerIoData. - HTTP/2 WebBrokerBridge — Invalid pointer operation em
sgcFree(oResponse)emTsgcWSHTTPServer.OnHTTP2RequestEventquando o DataSnap REST tratava um frame HTTP/2 apenas comHEADERS.
Atualização
A 2026.5 é uma atualização drop-in para projetos 2026.4 existentes. Nenhuma alteração de interface foi feita nos componentes existentes; os novos componentes de rate-limit / circuit-breaker / chaves de API são aditivos e opt-in. O modo de alto desempenho do HTTP.sys está protegido por FineTune.OperatingMode := ompHighPerf — o código existente permanece no caminho clássico.
Clientes com uma assinatura ativa podem baixar o novo build na área do cliente. Usuários de avaliação podem obter o instalador atualizado em esegece.com/products/sgcwebsockets/sgcwebsockets-download.
Dúvidas, feedback ou ajuda com migração? Entre em contato — você receberá uma resposta das pessoas que escreveram o código.
