...

Definições do TCP Keepalive: Otimização no contexto do alojamento

TCP Keepalive determina a rapidez com que um servidor reconhece e termina as sessões TCP inactivas - uma alavanca de controlo que tem um impacto direto no consumo de recursos, na latência e no comportamento do tempo de inatividade no alojamento. Com valores adequados de inatividade, intervalo e sonda, reduzo os pontos mortos de ligação, evito quedas de NAT e mantenho as aplicações Web em Configurações de alojamento acessível de forma fiável.

Pontos centrais

  • ParâmetrosDefinir sondas inactivas, de intervalo, de forma direcionada
  • DemarcaçãoTCP Keepalive vs. HTTP Keep-Alive
  • Por tomadaSubstituições por serviço/pod do Kubernetes
  • Firewall/NATTempo de inatividade: considerar ativamente os tempos de inatividade
  • MonitorizaçãoMedição, testes de carga, afinação iterativa

Como funciona o TCP Keepalive

Eu ativo Manter vivo a nível da tomada ou do sistema, de modo a que a pilha envie pequenas sondas a intervalos definidos quando inativa. Após um tempo de espera ajustável (inativo), o sistema envia a primeira verificação; seguem-se outras sondas no intervalo definido até ser atingido o número de tentativas. Se a estação remota permanecer muda, termino a ligação e devolvo os descritores de ficheiros e os buffers no ficheiro Kernel livre. A lógica é claramente diferente da das retransmissões, porque o Keepalive verifica o estado de vivacidade de um fluxo que, de outra forma, estaria inativo. Particularmente em ambientes de alojamento com muitas sessões simultâneas, este comportamento evita fugas de informação que, de outra forma, eu só notaria em situações de elevada vivacidade. Carga sentir.

Porque é que o Keepalive conta no alojamento

Clientes com falhas, redes móveis e gateways NAT agressivos deixam muitas vezes para trás Ligações de zombies, que permanecem abertos durante muito tempo sem keepalive. Isso custa soquetes abertos, RAM e CPU em processos de aceitação, trabalho e proxy, o que aumenta o tempo de resposta. Eu uso valores adequados para remover esses corpos mortos logo no início e manter ouvintes, backends e upstreams abertos. reativo. O efeito é particularmente notório durante os picos de carga, porque menos ligações mortas enchem as filas de espera. Por isso, planeio o Keepalive juntamente com os timeouts HTTP e TLS e asseguro um harmonioso Interação em todos os níveis.

Parâmetros Sysctl: valores práticos

O Linux fornece valores padrão muito longos que são usados em Ambientes de alojamento raramente servem. Para os servidores Web, costumo definir um tempo de inatividade muito mais curto, de modo a eliminar atempadamente as sessões pendentes. Mantenho o intervalo entre sondas moderado, de modo a reconhecer rapidamente as falhas, mas sem inundar a rede com verificações. Equilibro o número de sondas entre os falsos alarmes e o tempo de deteção; menos sondas encurtam o tempo até que o Recursos. Para o IPv6, presto atenção às respectivas variáveis net.ipv6 e mantenho ambos os protocolos consistentes.

Parâmetros Padrão (Linux) Recomendação de alojamento Benefício
tcp_keepalive_time 7200s 600-1800s Quando a primeira amostra é enviada após o modo inativo
tcp_keepalive_intvl 75s 10-60s Distância entre sondas individuais
tcp_keepalive_probes 9 3-6 Máximo de tentativas falhadas antes de fechar

Eu defino os valores base em todo o sistema e aplico-os permanentemente via sysctl para que as reinicializações não descartem o trabalho de ajuste. Além disso, eu documento os valores iniciais e meço os efeitos em Taxas de erro e latências. Isto permite-me manter um equilíbrio entre a deteção rápida e o tráfego de rede adicional. Costumo usar as seguintes linhas como ponto de partida e ajustá-las posteriormente para cada carga de trabalho:

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5
sysctl -p

Ajuste por socket e plataforma

As predefinições globais raramente são suficientes para mim; defino por serviço Por tomada-para que backends sensíveis vivam mais tempo enquanto frontends limpam rapidamente. Em Python, Go ou Java, defino SO_KEEPALIVE e as opções TCP específicas diretamente no socket. No Linux, controlo através de TCP_KEEPIDLE, TCP_KEEPINTVL e TCP_KEEPCNT, enquanto o Windows funciona através de chaves de registo (KeepAliveTime, KeepAliveInterval). No Kubernetes, substituo as configurações em uma base específica de pod ou implantação para tratar gateways de API de curta duração de maneira diferente dos de longa duração Base de dados-proxies. Para configurações de contentores, também verifico as tabelas NAT do anfitrião e os plug-ins CNI porque os fluxos inactivos são frequentemente removidos mais cedo do que eu gostaria.

Exemplo # (Python, Linux)
importar socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)

HTTP Keep-Alive vs. TCP Keepalive

O HTTP Keep-Alive mantém as ligações abertas para vários pedidos, enquanto o TCP O Keepalive fornece verificações puras de vivacidade ao nível do transporte. Ambos os mecanismos se complementam, mas funcionam com objectivos e temporizadores diferentes. Em HTTP/2 e HTTP/3, os quadros PING assumem parcialmente o papel do Keepalive, mas continuo a proteger adicionalmente a camada TCP. Defino o timeout HTTP de acordo com a visão da aplicação, enquanto defino os valores TCP com base no lançamento económico de Recursos alinhar. Se quiser saber mais pormenores sobre a página HTTP, pode encontrar um guia útil em Tempo limite do HTTP Keep-Alive.

Afinação do tempo limite da rede: prática

Para front-ends clássicos de alojamento web, trabalho frequentemente com 300s de inatividade, 30-45s de intervalo e 4-6 sondas para terminar sessões inactivas rapidamente e Filas de espera magra. As ligações à base de dados têm mais paciência para que as fases de ocupação curtas não provoquem desligamentos desnecessários. Nos gateways de ponta ou de API, também reduzo os tempos de espera porque há muitas ligações de curta duração. Harmonizo os valores com os tempos limite do aperto de mão TLS, os tempos limite de leitura/escrita e os limites de tempo a montante, para que não haja contradições nos limites das camadas. Para uma otimização passo-a-passo, é necessário um Fluxo de afinação, que utilizo nas janelas de manutenção.

Tempo limite de inatividade da firewall, NAT e nuvem

Muitas firewalls e gateways NAT cortam os fluxos inactivos após 300-900 segundos, razão pela qual eu Manter vivo para que o meu intervalo seja inferior a este. Caso contrário, a aplicação não reconhecerá o término até o próximo pedido e causará novas tentativas desnecessárias. Em balanceadores de carga na nuvem, verifico os parâmetros TCP ou de conexão ociosa e comparo-os com os valores de sysctl e proxy. Em configurações anycast ou multi-AZ, verifico se as alterações de caminho conduzem a estações remotas aparentemente mortas e aumento especificamente o número de amostras para estas zonas. Eu documento a cadeia de cliente, proxy, firewall e backend para que eu possa Causas para gotas rapidamente.

Integração na configuração do servidor Web

O Apache, o Nginx e o HAProxy organizam a persistência HTTP a nível da aplicação, enquanto o sistema operativo TCP O Keepalive cumpre. No Apache, ligo o KeepAlive, limito os KeepAliveRequests e mantenho o KeepAliveTimeout curto para que os trabalhadores sejam libertados prontamente. Utilizo o Nginx com um keepalive_timeout curto e keepalive_requests moderados para uma reutilização eficiente. No HAProxy, uso opções de soquete como tcpka ou padrões do lado do sistema para que os tempos limite de transporte correspondam à política de proxy. Para aspectos mais aprofundados do servidor web, o Guia de afinação do servidor Web, que combino com as minhas personalizações TCP.

Monitorização, testes e métricas

Meço o efeito de cada ajustamento e não me baseio em Pressentimento. ss, netstat e lsof mostram-me quantas ligações ESTABLISHED, FIN_WAIT e TIME_WAIT estão presentes e se as fugas estão a aumentar. Nas métricas, monitorizo aborts, RSTs, retransmissões, latência P95/P99 e comprimentos de fila; se um valor atinge os seus limites, vou especificamente para Idle, Interval ou Probes. Utilizo testes de carga sintéticos (por exemplo, ab, wrk, Locust) para simular padrões de utilização reais e verificar se a afinação cumpre as métricas pretendidas. Aplico as alterações por fases e comparo as séries cronológicas antes de global Distribuir as predefinições por todos os anfitriões.

Imagens de erros e resolução de problemas

Se definir intervalos demasiado curtos, inflaciono o Tráfego de rede e aumentam o risco de as falhas temporárias serem interpretadas como falhas. Se houver muito poucas sondas, fecho as ligações activas em redes lentas, o que os utilizadores encontram como uma mensagem de erro esporádica. Os tempos de inatividade demasiado longos, por outro lado, levam ao congestionamento de sockets e a crescentes atrasos na aceitação. Verifico os registos de RST do cliente/servidor, ECONNRESET e ETIMEDOUT para reconhecer a direção. Se afetar principalmente os utilizadores móveis, ajusto as sondas e os intervalos, porque há Pontos mortos e os problemas de sono ocorrem com mais frequência.

Predefinições seguras para várias cargas de trabalho

Começo com valores conservadores que são adequados para a produção e aperfeiçoo-os depois de medir o Carga de trabalho. As APIs da Web geralmente exigem tempos de inatividade curtos, as bases de dados são significativamente mais longas. Os proxies entre zonas ou fornecedores beneficiam de um pouco mais de sondas para lidar com a flutuação do caminho. Para aplicações interactivas, reduzo o intervalo e aumento o número de sondas de modo a detetar erros mais rapidamente, mas sem os fechar prematuramente. A tabela dá-me uma orientação compacta, que ajusto durante a operação.

Tipo de servidor Inativo Intervalo Provas Nota
Frontend de alojamento Web 300-600s 30-45s 4-6 Sessões curtas, volume elevado
gateway de API 180-300s 20-30s 5-6 Muitas fases de inatividade, desaparecem rapidamente
Proxy de base de dados 900-1800s 45-60s 3-5 Estabelecer uma ligação é dispendioso, é preciso ter paciência
Pod Kubernetes 600-900s 30-45s 4–5 Sincronizar com os tempos limite do CNI/LB

TCP_USER_TIMEOUT e backoff de retransmissão

Para além do Keepalive, utilizo especificamente o seguinte para ligações de transporte de dados TCP_USER_TIMEOUT, para controlar quanto tempo os dados não confirmados podem permanecer no soquete antes que a conexão seja ativamente cancelada. Isto é particularmente importante para proxies e APIs, que não devem passar por cabides durante minutos a fio. Em contraste com o Keepalive (que verifica a vivacidade durante a inatividade), o TCP_USER_TIMEOUT tem efeito quando os dados estão a fluir mas não são devolvidos ACKs - por exemplo, no caso de falhas assimétricas. Eu defino-o por tomada ligeiramente abaixo dos tempos limite de leitura/escrita da aplicação, para que o nível de transporte não espere mais tempo do que a lógica da aplicação em caso de erro.

Exemplo # (Go, Linux) - Keepalive e TCP_USER_TIMEOUT
d := net.Dialer{
    Timeout: 5 * time.Second,
    KeepAlive: 30 * time.Second,
    Controlo: func(rede, endereço string, c syscall.RawConn) erro {
        var err erro
        c.Controlo(func(fd uintptr) {
            // São permitidos 20s de dados não confirmados
            err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 0x12, 20000) // TCP_USER_TIMEOUT
        })
        return err
    },
}
conn, _ := d.Dial("tcp", "example:443")

Não estou a esquecer que o backoff TCP (extensão RTO) e as tentativas (tcp_retries2) também influenciam o comportamento em caso de perda de pacotes. Os tempos limite do utilizador demasiado curtos podem levar a desistências em redes difíceis, mesmo que a estação remota esteja acessível. Por isso, só os defino com rigor quando pretendo deliberadamente uma deteção rápida de erros (por exemplo, no proxy de extremo).

IPv6 e caraterísticas do sistema operativo

As mesmas opções por socket (TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT) aplicam-se ao IPv6. Dependendo da versão do kernel, os padrões globais para v4 e v6 se aplicam juntos; eu verifico isso com ss -o para conexões reais. No Windows, eu personalizo as predefinições através do registo (KeepAliveTime, KeepAliveInterval) e uso SIO_KEEPALIVE_VALS para sockets individuais. As opções são por vezes chamadas de forma diferente nos derivados do BSD, mas a semântica permanece a mesma. É importante verificar para cada plataforma se as substituições de aplicativos realmente superam os padrões do sistema e se os tempos de execução do contêiner herdam os namespaces corretamente.

WebSockets, gRPC e streaming

Fluxos de longa duração (WebSocket, gRPC, eventos enviados pelo servidor) se beneficiam particularmente de keepalives bem dosados. Eu começo em dois níveis: A aplicação envia pings/PONGs periódicos (por exemplo, nível WebSocket), enquanto a camada TCP protege com intervalos moderados. Isso evita que os NATs removam silenciosamente os fluxos. Para os clientes móveis, aumento o número de sondas e selecciono intervalos mais longos para ter em conta os modos de poupança de energia. Para o gRPC/HTTP-2, coordeno os PINGs HTTP/2 com o TCP Keepalive para não sondar duas vezes de forma demasiado agressiva e esgotar as baterias.

Tabelas Conntrack, kernel e NAT

Nos anfitriões Linux com rastreio de ligação ativo, uma ligação demasiado curta nf_conntrack-O tempo limite pode levar a uma queda precoce - mesmo que a aplicação pense mais tempo. Por isso, sincronizo os temporizadores relevantes (por exemplo. nf_conntrack_tcp_timeout_established) com meus intervalos de keepalive para que uma amostra chegue com segurança antes do prazo final do conntrack. Em nós com NAT forte (NodePort, NAT de saída) eu planejo o tamanho da tabela conntrack e os baldes de hash para evitar pressão global sob carga. Configurações limpas de keepalive aliviam essas tabelas de forma mensurável.

Exemplo: Unidades de servidor proxy e web

No HAProxy, ativo especificamente o keepalive do lado do transporte e mantenho os tempos limite HTTP consistentes:

Extrato # (HAProxy)
predefinições
  tempo limite do cliente 60s
  timeout servidor 60s
  tempo limite de ligação 5s
  opção http-keep-alive
  option tcpka # Ativar TCP keepalive (utilizar as predefinições do SO)

aplicação backend
  servidor s1 10.0.0.10:8080 check inter 2s fall 3 rise 2

No Nginx, penso que a reutilização é eficiente sem sobrecarregar os trabalhadores:

Excerto do # (Nginx)
keepalive_timeout 30s;
keepalive_requests 1000;
proxy_read_timeout 60s;
proxy_send_timeout 60s;

Certifico-me de que os tempos limite do transporte e da aplicação se encaixam logicamente: A prevenção de „linhas mortas“ é a tarefa do TCP/Keepalive, enquanto os tempos limite da aplicação mapeiam a lógica empresarial e as expectativas do utilizador.

Observabilidade na prática

Verifico o funcionamento do Keepalive em direto no anfitrião:

  • ss: ss -tin 'sport = :443' espectáculos com -o o temporizador (por exemplo. timer:(keepalive,30sec,0)), número de tentativas e Q de envio/recebimento.
  • tcpdumpFiltro uma ligação inativa e vejo pequenos pacotes/ACKs periódicos durante as fases de inatividade. Isto permite-me reconhecer se as sondas activam o NAT a tempo.
  • Registos/MétricasCorrelaciono os picos de RST/timeout com as alterações de inatividade/intervalo/sondas. Uma queda nos sockets abertos com carga constante mostra que a arrumação foi bem sucedida.

Para testes reproduzíveis, simulo falhas de ligação (por exemplo, interface em baixo, iptables DROP) e observo a rapidez com que os trabalhadores/processos libertam recursos e se as tentativas funcionam corretamente.

Planeamento de recursos e capacidades

O keepalive é apenas parte do equilíbrio. Certifico-me de que o ulimit/nofile, fs.file-max, net.core.somaxconn e tcp_max_syn_backlog correspondem ao meu número de ligação. Os tempos de inatividade demasiado longos escondem défices aqui, enquanto os valores demasiado curtos trazem uma suposta estabilidade mas atingem duramente os utilizadores. Eu planeio buffers (Recv-/Send-Q) e reservas FD com cenários de carga e meço quantas conexões ociosas simultâneas meus nós podem realmente suportar antes que o GC/Worker e as filas de aceitação sofram.

Quando não dependo (apenas) do TCP Keepalive

Para tráfego puramente interno sem NAT, um número reduzido de ligações e timeouts claros da aplicação, por vezes dispenso keepalives agressivos e deixo a deteção para a aplicação (por exemplo, heartbeats ao nível do protocolo). Por outro lado, em cenários de ponta e móveis, dou prioridade a intervalos curtos, poucas sondas e adiciono PINGs HTTP/2 ou pings WebSocket. É importante que eu nunca faça a sintonia isoladamente: Os valores de keepalive devem estar em harmonia com as tentativas, os disjuntores e as estratégias de backoff, para que eu possa detetar erros rapidamente, mas sem causar a oscilação do sistema.

Estratégia de implantação e validação

Estou a implementar novas predefinições passo a passo: Primeiro os anfitriões Canary, depois uma AZ/zona e depois toda a frota. As comparações antes/depois incluem conexões abertas, CPU no modo kernel, latência P95/P99, taxas de erro e retransmissões. No Kubernetes, testo por meio de anotações de pod ou contêineres de inicialização que definem namespaces sysctl antes de alterar todo o nó. Desta forma, minimizo o risco e asseguro resultados reproduzíveis - e não apenas melhorias perceptíveis.

Brevemente resumido

Com um planeamento bem pensado TCP Definições Keepalive, removo as ligações inactivas mais cedo, reduzo a pressão sobre os recursos e estabilizo os tempos de resposta. Escolho tempos de inatividade curtos para o frontend, valores mais longos para backends com estado e protejo-me com intervalos moderados e poucas ou médias sondas. Harmonizo os valores com os tempos limite de HTTP, TLS e proxy e mantenho-os abaixo dos limites de inatividade da firewall e do NAT. Após cada ajuste, meço os efeitos visíveis na latência, nos erros e na CPU, em vez de confiar na intuição. É assim que consigo fiável Plataforma capaz de lidar melhor com picos de carga e de servir uniformemente os fluxos de utilizadores.

Artigos actuais