GEOADD与BRPOP达到一定负载后Docker部署Redis返回连接错误
问题根因
报错是两个问题叠加导致的,和Redis服务端配置无关:
- 客户端死循环疯狂创建Redis连接:你写的通知拉取逻辑有严重缺陷:
select块里加default分支的写法,会导致只要WebSocket连接没断开,循环就会无等待执行BRPOP调用。一旦BRPOP因为连接错误、上下文取消、连接池满等原因快速返回,代码没有任何退避间隔,立刻发起下一次调用,短时间内会创建海量TCP连接。从Redis INFO返回的total_connections_received:1271也能印证这点:正常复用连接池的场景下,客户端到Redis的连接数不会短时间内涨到上千。另外你设置BRPOP超时为0无限阻塞,会长期占用连接不释放,从INFO里的blocked_clients:81能看到,已经有81个连接被阻塞占住,很快就会打满go-redis默认的连接池容量,后续请求只能不断新建TCP连接。 - 本地进程文件描述符上限过低:你只给Docker里的Redis容器配置了
nofile参数,这个配置只对容器内的Redis进程生效,对你Mac本地直接运行的Go进程完全无效。Mac系统默认给单个进程分配的文件描述符软上限只有256,每个WebSocket连接、每个到Redis的TCP连接都要占用一个fd,70个业务连接加上疯狂新建的Redis连接,很快就会耗尽所有可用fd,触发socket: too many open files错误。此时连DNS解析需要读取系统hosts、resolv.conf文件都拿不到fd,就会偶发lookup localhost: no such host的连带报错。
修复方案
1. 修复BRPOP死循环逻辑
删掉错误的default空转轮询写法,给BRPOP设置合理的超时时间,调用出错后加退避间隔,避免无意义的疯狂重试:
go func() { defer close(driverDataCh) for { select { case <-closeRead.Done(): return default: } // 给BRPOP设置30s超时,不要用0无限阻塞 status, err := config.Redis.DriverPullStatus(ctx, driverID, 30*time.Second) if err != nil { // 连接关闭、键不存在等正常场景直接继续循环 if errors.Is(err, context.Canceled) || errors.Is(err, redis.Nil) { continue } // 其他网络错误、服务端错误等1s后再重试,避免打满服务端 time.Sleep(time.Second) continue } // 写channel的时候也要监听连接关闭信号,避免goroutine泄漏 select { case <-closeRead.Done(): return case driverDataCh <- &DriverData{Status: status.Status, DriverId: status.DriverID, UserId: status.UserID}: } } }()
2. 显式配置Redis连接池参数
初始化Redis客户端时不要用默认配置,根据业务场景设置合理的连接池上限,避免无限制创建连接:
client := redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("%s:%s", host, port), Password: password, DB: 0, PoolSize: 100, // 最大连接数,按业务并发设置,100足够支撑上千司机同时在线 IdleTimeout: 5 * time.Minute, // 空闲连接回收时间 DialTimeout: time.Second, // 建连超时 ReadTimeout: time.Second, // 读超时 WriteTimeout: time.Second, // 写超时 })
3. 调高Mac本地进程的文件描述符上限
当前终端临时生效直接执行命令:
ulimit -n 65536
要永久生效的话,把上面这行加到~/.zshrc(如果用zsh)或者~/.bash_profile(如果用bash)末尾,保存后执行source对应配置文件即可。
4. 修复验证
重启服务后压测WebSocket连接,观察Redis INFO输出:connected_clients会稳定在你配置的连接池大小附近,不会持续上涨,total_connections_received增速会大幅下降,之前的两个报错都会消失。
内容的提问来源于stack exchange,提问作者Sami Al-Subhi
相关产品推荐
相关产品推荐

