使用短连接访问Redis出现“Cannot assign requested address”错误
问题描述
应用程序通过短连接访问Redis实例时,报错:Cannot assign requested address。
问题分析
出现这种错误的应用程序使用的架构基本都是php-fpm加上phpredis,这种架构在并发量较大的情况下,处于TIME-WAIT状态下的TCP连接数较多,客户端无法分配出新的端口,则会出现“Cannot assign requested address”问题。
处理方案
- 方案一:使用pconnect替换connect。
此方案的思路是用长连接替代短连接,减少TCP连接,同时可以避免每次请求都会重新建立连接的问题,减少延时。
之前连接Redis的代码如下:
$redis->connect('${Hostname}',${Port}); $redis->auth('${Inst_Password}');
现使用pconnect替换connect,即使用persistent connection的方式连接。
$redis->pconnect('${Hostname}', ${Port}, 0, NULL, 0, 0, ['auth' => ['${Inst_Password}']]);
- 示例中的连接参数请根据业务实现情况修改,${Hostname}、${Port}和${Inst_Password}为Redis实例的连接地址、端口号和密码。
- PhpRedis应为5.3.0及以上版本,且建议使用这种pconnect初始化方式,避免断连时出现no auth问题。
- 方案二:修改客户端所在ECS实例的tcp_max_tw_buckets内核参数。
此方案的思路是直接复用处于TIME-WAIT状态的端口,但是如果ECS和后端服务之间有重传,连接可能会失败,所以建议使用pconnect的方案。
一般情况推荐使用方案一,对于一些特定场景(业务代码牵涉过多组件不易变更等场景),需要更快的满足高并发,可以使用方案二