¿Qué puedo hacer si se devuelve el error "Cannot assign requested address" cuando accedo a Redis usando connect?
Síntomas
El mensaje de error "Cannot assign requested address" aparece cuando se accede a Redis mediante connect.
Análisis
Las aplicaciones que encuentran este error suelen usar php-fpm y phpredis. En escenarios de alta concurrencia, un gran número de conexiones TCP están en el estado TIME-WAIT. Como resultado, el cliente no puede asignar los nuevos puertos y se devolverá el mensaje de error.
Soluciones
- Solución 1: Utilice pconnect en lugar de connect.
El uso de pconnect reduce el número de conexiones TCP y evita que las conexiones se restablezcan para cada solicitud y, por lo tanto, reduce la latencia.
Cuando se utiliza connect, el código para conectarse a Redis es el siguiente:
$redis->connect('${Hostname}',${Port}); $redis->auth('${Inst_Password}');
Reemplace connect por pconnect y el código se convertirá en:
$redis->pconnect('${Hostname}', ${Port}, 0, NULL, 0, 0, ['auth' => ['${Inst_Password}']]);
- Reemplace los parámetros de conexión del ejemplo con los valores reales. ${Hostname}, ${Port} y ${Inst_Password} son la dirección de conexión, el número de puerto y la contraseña de la instancia de Redis, respectivamente.
- phpredis debe ser v5.3.0 o posterior. Se recomienda utilizar este modo de inicialización pconnect para evitar los errores NOAUTH durante la desconexión.
- Solución 2: Modifique el parámetro tcp_max_tw_buckets del ECS donde se encuentra el cliente.
En esta solución, se reutilizan los puertos utilizados por las conexiones TIME-WAIT. Sin embargo, si se produce la retransmisión entre el ECS y el servicio de backend, la conexión puede fallar. Por lo tanto, se recomienda la solución pconnect.
- Conéctese al ECS donde se encuentra el cliente
- Ejecute el siguiente comando para comprobar los parámetros ip_local_port_range y tcp_max_tw_buckets:
sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
La información que aparecerá en pantalla será similar a la información siguiente:
net.ipv4.tcp_max_tw_buckets = 262144 net.ipv4.ip_local_port_range = 32768 61000
- Ejecute el siguiente comando para establecer el parámetro tcp_max_tw_buckets en un valor menor que el valor de ip_local_port_range:
sysctl -w net.ipv4.tcp_max_tw_buckets=10000
Generalmente, se recomienda la solución 1. En los escenarios especiales (por ejemplo, el código de servicio implica demasiados componentes y es difícil de cambiar), la solución 2 se puede usar para cumplir con los requisitos de alta simultaneidad.