客户端和网络连接 进阶排查 Jedis连接池报错 出现Read timed out 或Could not get a resource from the pool 排查是否使用了keys命令,keys命令会消耗大量资源,造成Redis阻塞。建议使用scan命令替代,且避免频繁执行。 使用短连接访问Redis出现“Cannot assign requested address”错误 问题描述 应用程序通过短连接访问Redis实例时,报错:Cannot assign requested address。 问题分析 出现这种错误的应用程序使用的架构基本都是phpfpm加上phpredis,这种架构在并发量较大的情况下,处于TIMEWAIT状态下的TCP连接数较多,客户端无法分配出新的端口,则会出现“Cannot assign requested address”问题。 处理方案 方案一:使用pconnect替换connect。 此方案的思路是用长连接替代短连接,减少TCP连接,同时可以避免每次请求都会重新建立连接的问题,减少延时。 之前连接Redis的代码如下: $redis>connect('${Hostname}',${Port}); $redis>auth('${InstPassword}'); 现使用pconnect替换connect,即使用persistent connection的方式连接。 $redis>pconnect('${Hostname}', ${Port}, 0, NULL, 0, 0, ['auth' > ['${InstPassword}']]); 说明 示例中的连接参数请根据业务实现情况修改,${Hostname}、${Port}和${InstPassword}为Redis实例的连接地址、端口号和密码。 PhpRedis应为5.3.0及以上版本,且建议使用这种pconnect初始化方式,避免断连时出现no auth问题。 方案二:修改客户端所在ECS实例的tcpmaxtwbuckets内核参数。 此方案的思路是直接复用处于TIMEWAIT状态的端口,但是如果ECS和后端服务之间有重传,连接可能会失败,所以建议使用pconnect的方案。 a. 连接客户端所在ECS实例。 b. 执行以下命令,查看iplocalportrange和tcpmaxtwbuckets参数。 sysctl net.ipv4.tcpmaxtwbuckets net.ipv4.iplocalportrange 系统显示类似如下: net.ipv4.tcpmaxtwbuckets 262144 net.ipv4.iplocalportrange 32768 61000 c. 执行以下命令,修改tcpmaxtwbuckets参数,确保tcpmaxtwbuckets的值比iplocalportrange范围的值小。 sysctl w net.ipv4.tcpmaxtwbuckets10000 一般情况推荐使用方案一,对于一些特定场景(业务代码牵涉过多组件不易变更等场景),需要更快的满足高并发,可以使用方案二