このトピックでは、クライアントが短期間の接続でApsaraDB for Redisインスタンスにアクセスしたときに発生する [要求されたアドレスを割り当てられません]
エラーを解決する方法について説明します。
原因
このエラーが発生したアプリケーションは、主にphp-fpmとphpredisを使用します。 このアーキテクチャでは、多数の同時要求が処理されている場合、TIME − WAIT状態のTCP接続が増加し、クライアントは新しいポートを割り当てることができない。 この場合、[Cannot assign requested address]
エラーが返されます。
解決策
connectの代わりにpconnectを使用する (推奨)
connectの代わりにpconnectを使用すると、TCP接続の数が減り、要求ごとに接続が再確立されるのを防ぎ、待ち時間が短縮されます。
次のコードは、connectを使用してApsaraDB for Redisインスタンスに接続する方法の例を示しています。
$redis->connect('[$Hostname]', [$Port]);
$redis->auth('[$Inst_Password]');
パラメーターの説明: [$Hostname] 、[$Port] 、および [$Inst_Password] はそれぞれ、ApsaraDB for Redisインスタンスのエンドポイント、ポート番号、およびパスワードを示します。 詳細については、「エンドポイントの表示」をご参照ください。
次のコードは、pconnectを使用してインスタンスに接続する方法の例を示しています。 このようにして、持続的な接続は、短期間の接続の代わりに確立される。
$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.
クライアントをホストするECSインスタンスのtcp_max_tw_bucketsカーネルパラメーターの変更
アプリケーションコードに多数のコンポーネントが含まれ、変更が困難なシナリオでは、このソリューションを使用して高い同時実行要件を満たすことができます。
このソリューションでは、tcp_max_tw_bucketsの値が直接変更されます。 しかし、サーバが5タプルを含むパケットを再送信するときにサーバがまだLAST-ACK状態にある場合、接続は確立されない。 したがって、pconnectソリューションを使用することを推奨します。
クライアントがデプロイされているECS (Elastic Compute Service) インスタンスにログインします。
次のコマンドを実行して、ip_local_port_rangeおよびtcp_max_tw_bucketsパラメーター値を表示します。
sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
サンプル出力:
net.ipv4.tcp_max_tw_buckets = 262144 net.ipv4.ip_local_port_range = 32768 61000
次のコマンドを実行して、tcp_max_tw_bucketsをip_local_port_rangeより小さい値に設定します。
この例では、ipv4.ip_local_port_rangeは32768〜61000のポート範囲に設定されています。 tcp_max_tw_bucketsを32768より小さい値に設定する必要があります。 サンプルコマンド:
sysctl -w net.ipv4.tcp_max_tw_buckets=10000
注意事項
tcp_tw_recycleはLinux 4.12の時点で削除されました。 したがって、tcp_tw_reuseおよびtcp_tw_recycleの値を変更する必要があるソリューションは、NATまたはLinux Virtual Server (LVS) を使用するサービスには適用できなくなりました。 このようなソリューションは使用しないことをお勧めします。