O que posso fazer se o erro "Cannot assign requested address" for retornado ao acessar o Redis usando o connect?
Sintoma
A mensagem de erro "Cannot assign requested address" é retornada quando você acessa o Redis usando connect.
Análise
Aplicações que encontram este erro normalmente usam php-fpm e phpredis. Em cenários de alta concorrência, um grande número de conexões TCP estão no estado TIME-WAIT. Como resultado, o cliente não pode alocar novas portas e a mensagem de erro será retornada.
Soluções
- Solução 1: use pconnect em vez de connect.
O uso do pconnect reduz o número de conexões TCP e impede que as conexões sejam restabelecidas para cada solicitação e, portanto, reduz a latência.
Ao usar o connect, o código para se conectar ao Redis é o seguinte:
$redis->connect('${Hostname}',${Port}); $redis->auth('${Inst_Password}');
Substitua connect por pconnect, e o código se torna:
$redis->pconnect('${Hostname}', ${Port}, 0, NULL, 0, 0, ['auth' => ['${Inst_Password}']]);
- Substitua os parâmetros de conexão no exemplo por valores reais. ${Hostname}, ${Port} e ${Inst_Password} são o endereço de conexão, o número da porta e a senha da instância do Redis, respectivamente.
- phpredis deve ser v5.3.0 ou posterior. Recomendamos que você use este modo de inicialização do pconnect para evitar erros NOAUTH durante a desconexão.
- Solução 2: modifique o parâmetro tcp_max_tw_buckets do ECS no qual o cliente está localizado.
Nesta solução, as portas usadas pelas conexões TIME-WAIT são reutilizadas. No entanto, se a retransmissão ocorrer entre o ECS e o serviço de back-end, a conexão poderá falhar. Portanto, a solução pconnect é recomendada.
- Conecte-se ao ECS onde o cliente está localizado
- Execute o seguinte comando para verificar os parâmetros ip_local_port_range e tcp_max_tw_buckets:
sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
Informação semelhante à seguinte foi exibida:
net.ipv4.tcp_max_tw_buckets = 262144 net.ipv4.ip_local_port_range = 32768 61000
- Execute o seguinte comando para definir o parâmetro tcp_max_tw_buckets para um valor menor que o valor de ip_local_port_range:
sysctl -w net.ipv4.tcp_max_tw_buckets=10000
Geralmente, a solução 1 é recomendada. Em cenários especiais (por exemplo, o código de serviço envolve muitos componentes e é difícil de mudar) a solução 2 pode ser usada para atender aos altos requisitos de simultaneidade.