This topic describes how to resolve the Cannot assign requested address
error that occurs when a client accesses a Tair (Redis OSS-compatible) instance over a short-lived connection.
Cause
Applications that experience this error mostly use php-fpm and phpredis. In this architecture, when a large number of concurrent requests are being processed, TCP connections in the TIME-WAIT state increase and the client cannot allocate new ports. In this case, the Cannot assign requested address
error is returned.
Solution
Use pconnect instead of connect (recommended)
Using pconnect instead of connect reduces the number of TCP connections and prevents connections from being re-established for each request, and therefore reduces latency.
The following code provides an example on how to connect to a Tair (Redis OSS-compatible) instance by using connect:
$redis->connect('[$Hostname]', [$Port]);
$redis->auth('[$Inst_Password]');
Parameter description: [$Hostname], [$Port], and [$Inst_Password] respectively indicate the endpoint, port number, and password of the Tair (Redis OSS-compatible) instance. For more information, see View endpoints.
The following code provides an example on how to connect to the instance by using pconnect. This way, persistent connections are established instead of short-lived connections.
$redis->pconnect('[$Hostname]', [$Port], 0, NULL, 0, 0, ['auth' => ['[$Inst_Password]']]);
// If the version of phpredis is 5.3.0 or later, we recommend that you use pconnect to prevent NOAUTH errors during disconnection.
// Modify the values of the timeout, persistent_id, retry_interval, and read_timeout parameters based on your business requirements.
Modify the tcp_max_tw_buckets kernel parameter of the ECS instance that hosts the client
In scenarios where the application code involves a large number of components and is difficult to change, you can use this solution to meet high concurrency requirements.
In this solution, the value of tcp_max_tw_buckets is directly modified. However, if the server is still in the LAST-ACK state when it retransmits packets that contain the 5-tuple, the connection fails to be established. Therefore, we recommend that you use the pconnect solution.
Log on to the Elastic Compute Service (ECS) instance where the client is deployed.
Run the following command to view the ip_local_port_range and tcp_max_tw_buckets parameter values.
sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
Sample output:
net.ipv4.tcp_max_tw_buckets = 262144 net.ipv4.ip_local_port_range = 32768 61000
Run the following command to set tcp_max_tw_buckets to a value smaller than the start value of the port range specified by ip_local_port_range.
In this example, ipv4.ip_local_port_range is set to a port range from 32768 to 61000. You must set tcp_max_tw_buckets to a value smaller than 32768. Sample command:
sysctl -w net.ipv4.tcp_max_tw_buckets=10000
Precautions
tcp_tw_recycle has been removed as of Linux 4.12. Therefore, solutions that require modification of the values of tcp_tw_reuse and tcp_tw_recycle are no longer applicable to services that use NAT or Linux Virtual Server (LVS). We recommend that you do not use such solutions.