协程调试需用cid标识日志、禁用xdebug、依赖swoole tracker查waiting状态及阻塞点,yasd/swoole-debugger仅限开发,须理解协程无栈共享特性。

协程里用 var_dump() 为什么看不到执行顺序?
因为协程是并发调度的,var_dump() 输出没有上下文隔离,多个协程的日志会挤在一块,根本分不清哪条是哪个协程打的。更麻烦的是,它不输出协程 ID,你连“谁干的”都搞不定。
- 必须配合
Swoole\Coroutine::getCid()使用,把 CID 打进日志:error_log("[cid:".Swoole\Coroutine::getCid()."] user_id=123"); - 别在 HTTP 响应体里用
var_dump()—— 它可能破坏 JSON 格式或触发 headers already sent 错误 - 高并发下
error_log()写文件有锁竞争,建议用Swoole\Logger或异步日志通道替代
为什么 Xdebug 在 Swoole 里断点经常跳错或失效?
Xdebug 是为传统同步请求设计的,而 Swoole 协程靠钩子拦截 IO 实现调度,Xdebug 的调用栈无法感知协程切换,导致断点位置错乱、堆栈断裂、甚至协程被卡死。
- 仅限开发环境启用,配置中必须设
xdebug.start_with_request=yes(不能靠 URL 参数触发) - PHP 启动时就要加载 Xdebug,
php server.php前确认php -m | grep xdebug有输出 - IDE 要监听
9003端口,Docker 场景下xdebug.client_host得填宿主机真实 IP,不是127.0.0.1 - 一旦发现协程 hang 住或响应变慢,立刻关掉 Xdebug —— 它对协程调度有可观干扰
用 Swoole Tracker 查协程卡死,关键要看哪几项?
Swoole Tracker 是目前唯一能真正还原协程生命周期和阻塞点的工具,它不依赖 PHP 层调试器,直接从扩展层抓取调度快照。
- 重点盯
coroutine_list输出里的state字段:值为WAITING且elapsed_time > 1000毫秒,大概率是 IO 阻塞或 Channel 死锁 - 检查
stack是否停留在co::sleep、Channel->pop或MySQL->query—— 这些是常见挂起点 - 配合
stats方法看全局指标:connection_count突增但request_count不涨,说明连接堆积在协程调度层
要不要上 YASD 或 Swoole-debugger?
可以,但得清楚它们的适用边界:YASD 是 C++ 写的底层调试器,支持实时注入断点,但安装复杂、文档少;Swoole-debugger 更轻量,支持多客户端连接,但只适用于单机开发环境,不兼容 Docker 网络隔离场景。
- 新手优先试
Swoole-debugger:启动服务后访问http://127.0.0.1:9502/debug就能进 Web 控制台 - 若需分析线上偶发卡顿,
Swoole Tracker+strace -p {pid} -e trace=epoll_wait,read,write组合更可靠 - 所有协程调试工具都绕不开一个事实:你得先理解
go()启动的协程不会继承父协程的局部变量,闭包捕获要格外小心










