本地Rails应用Puma服务器突发无响应,请求无法命中断点如何排查?
Puma无响应故障原因及排查方案
第一步:先抓取线程调用栈定位阻塞点
你启动Puma后拿到进程PID(你的示例日志里PID为12446,每次启动会更新),直接执行命令:kill -QUIT <Puma进程PID>
Puma收到信号后会在终端打印所有工作线程的完整调用栈,直接就能看到每个线程卡在哪一行代码,是最快的定位方式。
常见故障原因及对应排查方法
- 单进程模式下所有工作线程被IO阻塞
你的Puma运行在单进程模式,最大工作线程只有5个,只要有5个被阻塞的请求占满所有线程,后续所有请求都会直接卡住,根本到不了控制器层,所以你加的binding.pry不会触发。常见的阻塞场景包括:- 数据库连接池占满/有未释放的表锁/行锁,可以进入对应数据库执行
show processlist(MySQL)或select * from pg_stat_activity where state = 'active';(PostgreSQL)查看是否有长时间运行的挂起查询 - 调用外部HTTP/三方服务没有设置超时时间,请求一直挂起
- 依赖的缓存服务(Redis、Memcached)挂掉,客户端没有设置短超时不断重试
临时验证可以修改puma配置,增加worker进程数,测试是否有请求可以正常响应。
- 数据库连接池占满/有未释放的表锁/行锁,可以进入对应数据库执行
- 开发环境代码自动重载触发死锁
Rails 5.1.x版本在开发环境默认开启代码自动重载,存在已知的线程安全问题,容易触发死锁导致所有请求挂起。验证方式:修改config/environments/development.rb,将config.cache_classes改为true,config.reload_classes_only_on_change改为false,重启服务后测试是否能正常响应,如果恢复正常就属于该问题。 - 请求卡在中间件层未到达控制器
如果请求还没到ApplicationController就被上游中间件阻塞,自然触发不了控制器断点。你可以执行rails middleware列出当前项目加载的所有Rack中间件,排查近期新增的身份认证、监控、日志类中间件,逐个注释后测试是否恢复。 - 本地临时文件/权限异常
Rails运行依赖tmp目录下的缓存、套接字、PID文件,如果tmp目录满了、权限被修改,或者日志文件不可写,也会导致进程挂死。执行rm -rf tmp/*清空所有临时文件,再重启服务测试即可。 - IPv6解析异常
你的日志显示Puma同时监听IPv4和IPv6地址,部分系统的IPv6本地解析存在异常,会导致请求卡在内核网络层。可以启动服务时强制绑定IPv4地址:rails s -b 127.0.0.1,测试是否能正常响应。
环境排查验证
你可以新建一个空白的同版本Rails项目,用同样的Ruby、Puma版本启动测试,如果空白项目可以正常响应,就可以完全排除全局环境的问题,故障点100%在当前项目的配置、依赖或初始化逻辑中。
内容的提问来源于stack exchange,提问作者Manoj Pogadadanda
相关产品推荐
相关产品推荐

