服务重启时报 OSError: [Errno 98] Address already in use,ss 里看不到 LISTEN,只有 20 多条 TIME_WAIT 占着 8000 端口。乍看像缓存或者权限的锅,追下去往往不是。
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 8000))
s.listen(128)
追下去是这么回事:SO_REUSEADDR 必须在 bind 之前设置,代码里写在了 bind 之后,选项没有生效。残留的 TIME_WAIT 四元组让新进程无法立刻复用端口。
「SO_REUSEADDR」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。别只看报错的最后一行,往上看几行,真正的起因通常在上面。
同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。
具体做法是,把 setsockopt 移到 bind 之前;确认传进去的值是 1;检查是否还有旧进程持有端口;确需多进程监听再用 SO_REUSEPORT。
验收就看一点,连续快速重启 10 次都能立刻绑定成功,Errno 98 不再出现。
