All Products
Search
Document Center

The Cannot assign requested address error is returned when applications connect to ApsaraDB for Redis with short-lived connections.short-lived connection

Last Updated: Feb 19, 2021

Description

The following error is returned when applications connect to an ApsaraDB for Redis instance with short-lived connections:

Cannot assign requested address

Causes

Applications that experience such errors 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 is returned.

Solutions

Two solutions are available for this issue. We recommend that you use Solution 1: Use pconnect to replace connect. For some specific scenarios where the application code involves a large number of components that cannot be modified in a flexible way, you can use Solution 2: Modify the tcp_max_tw_buckets kernel parameter of the ECS instance where the client is deployed:

Solution 1: Use pconnect to replace connect

This solution uses persistent connections to replace short-lived connections to reduce TCP connections. This also avoids re-establishing connections upon each request and reduces network latency.

The following code is used to connect to an ApsaraDB for Redis instance before recommended solutions are used:

//Modify the connection parameters in this example based on your business scenarios.
$redis->connect('[$Hostname]', [$Port]);
$redis->auth('[$Inst_Password]');

Note: [$Hostname], [$Port], and [$Inst_Password] are separately the connection address, port number, and password of the ApsaraDB for Redis instance. For more information, see View endpoints.

The following code uses pconnect to replace connect. This way, persistent connections are established instead of short-lived connections.

//phpredis >= 5.3.0. We recommend that you use pconnect to connect to the ApsaraDB for Redis instance. This can avoid no auth when the client is disconnected.
//Modify the timeout, persistent_id, retry_interval, and read_timeout parameters based on application requirement.
//PhpRedis documentation.

$redis->pconnect('[$Hostname]', [$Port], 0, NULL, 0, 0, ['auth' => ['[$Inst_Password]']]);

Solution 2: Modify the tcp_max_tw_buckets kernel parameter of the ECS instance that hosts the client

This solution directly reuses the ports that are in the TIME-WAIT state. 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. However, for some specific scenarios where the application code involves a large number of components that cannot be modified in a flexible way, and high concurrency is required, you can choose this solution to avoid the Cannot assign requested address error.

  1. Connect to the ECS instance where the client is located. For more information about how to connect to an ECS instance, see Connect to instances.
  2. Run the following command to view the ip_local_port_range and tcp_max_tw_buckets parameters.
    sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
    The following output is returned.
    net.ipv4.tcp_max_tw_buckets = 262144
    net.ipv4.ip_local_port_range = 32768 61000
  3. Run the following command to modify the tcp_max_tw_buckets parameter. Make sure that the value of tcp_max_tw_buckets is smaller than that of ip_local_port_range.
    sysctl -w net.ipv4.tcp_max_tw_buckets=10000

More information

Ignore methods that require you to modify tcp_tw_reuse and tcp_tw_recycle. These methods are not applicable to services that use NAT or Linux Virtual Server (LVS). tcp_tw_recycle has been deprecated in Linux 4.12.

Applicability

  • ApsaraDB for Redis