Egg: [RFC] egg-bin debug

Created on 1 Sep 2017  ·  10Comments  ·  Source: eggjs/egg

背景

在 cluster 模式下,worker 自动重启后,debugPort 会变更,需要手动重新 attach,对调试带来不小的麻烦。

之前的解决方案是,通过 egg-development-proxyworker 插件,启动一个 tcp 代理 worker 的调试接口。

存在的问题:

  • 需要手动安装插件
  • vscode 里面需要配置

解决思路

  • 无需独立插件,egg-development-proxyworker 的代理功能直接做到 egg-bin debug 即可
  • egg-bin 就是 parent 进程,可以改下 egg-cluster 在 worker 重启后主动发一个 message 给 parent 通知新的 debugPort 即可
  • 自动判断 node 版本,8.x+ 则用 inspect,低版本用 debug
  • 自动读取 WebStorm 的环境变量
  • egg-development-proxyworker 的功能实现有点复杂,无需多个代理,直接独立一个inspector-proxy 即可
proposals

Most helpful comment

上述问题已解决,参见 https://github.com/atian25/blog/issues/25

All 10 comments

cc @eggjs/core 有什么建议

干!

@fengmk2 看最后那段,定下方案

根据最终讨论方案,更新了一楼,下面这段为原来的 RFC,备份用。

背景

在 cluster 模式下,worker 自动重启后,debugPort 会变更,需要手动重新 attach,对调试带来不小的麻烦。

之前的解决方案是,通过 egg-development-proxyworker 插件,启动一个 tcp 代理 worker 的调试接口。

存在的问题:

  • 需要手动安装插件
  • vscode 里面需要配置
  • 目前的 egg-bin debug 会启动 master / worker / agent 三个调试端口,但通常情况下不需要。

解决思路

调试代理

  • 无需独立插件,egg-development-proxyworker 的代理功能直接做到 egg-bin debug 即可
  • egg-bin 就是 parent 进程,可以改下 egg-core 在 worker 重启后主动发一个 message 给 parent 通知新的 debugPort 即可

调试端口

  • master 无需启动调试,故 egg-bin debug 不要传递 execArgv 而是作为 startClusteroptions
  • 默认不启动 agent 调试,需传递 --agent
  • 自动判断 node 版本,8.x+ 则用 inspect,低版本用 debug
// egg-bin debug 用法,然后转换为对应的 startCluster 参数
egg-bin debug --debug-port=5555 --agent=5554

对于 egg-cluster startCluster 的改造:

  • 自动检测 Node 版本,8.x+ 使用 inspect,否则用 debug 协议。
  • startCluster({}) 增加以下参数:

    • debug {Boolean | Number} - 是否调试 worker,如果未指定端口,则默认端口为 9229(inspect) or 5858(debug)

    • debugBrk {Boolean} - 是否调试 worker 时在第一行断点

    • debugAgent {Boolean | Number} - 是否调试 agent,如果未指定端口,则默认端口 -2 即为 9227(inspect) or 5856(debug)

    • debugAgentBrk {Boolean} - 是否调试 agent 时在第一行断点

需讨论:

  • 方案是否方向正确?
  • debug / debugAgent 是多态的,要拆分为 debugPort / debugAgentPort?
  • 这些 debug 参数要不要放到一个 object 里面

    • startCluster({ debugOptions: {} })

    • startCluster(options, debugOptions)

@atian25 方案你来定。

WebStorm 的 attach 原理,经过一些实验,猜测如下:

  • 会传递环境变量 NODE_DEBUG_OPTION ,在 inspect 协议下会传递 --inspect-brk=XXXX,旧协议传递 --debug-brk=XXXX --expose_debug_as=v8debug
  • 应用需把该调试端口传递给 execArgv 来启动调试
  • WebStorm 会首先 attach 该端口对应的 process
  • 然后会自动 attach 该 process 的所有开启 debug 的子程序(即包括我们的 agent 和所有 worker,包括重启后的 worker)

之前的修改导致的问题:

  • master 没有启动调试,只对 worker 启动了那个端口的调试
  • 此时会 attach 上 worker
  • 但当修改代码,导致 worker 重启时,调试端口对应的旧 worker 被杀掉,然后 WebStorm 就会视为调试结束,从而退出。

回归我们最终的诉求:

  • 不希望额外安装 proxywoker 插件
  • 简化 vscode 的调试配置
  • worker 重启后可以自动 attach

而之前的 egg-cluster 实现方式,实现过于复杂了,且导致 WebStorm 那问题解决起来麻烦,故:

  • 回滚 egg-cluster 那个 PR

    • 去除 debug / debugAgent / debugBrk / debugAgentBrk 的支持

    • master 照样启动调试

    • agent 调试跟随 master,固定端口为 5856

  • egg-bin debug --proxy=9999

    • 在 9999 端口启动 proxy 服务,代理到 worker 的 debug port

    • 监听 worker 的 debug 消息,自动 attach 重启后的新 worker

    • 在 8.x 新调试协议中,同时会代理 devtools 的调试界面,统一为一个 URL,不用每次都重新获取。

  • egg-development-proxyworker 废弃掉

先关了,vscode 插件的后面另起

目前 egg-bin debug --inspect-brk 会同时导致 master / agent / worker 都被断点住,需要人工去一次
attach 3 个进程,有点略麻烦,有时候只希望断点 worker 或 agent。

改进思路:

  • 使用 chrome-remote-interface 来主动 attach 进程,然后调用 Debugger.resume()
  • 在 egg-bin debug 的启动逻辑里面,默认会 attach master 和 agent,只允许断点在 worker 第一行。
  • 支持 --agent-brk --master-brk 两个参数,来断点其他两个进程。

其他需要顺便优化的:

  • WebStorm 环境下,无需启动 InspectorProxy 和上述逻辑
  • context.debugPort 应该提供默认值

上述问题已解决,参见 https://github.com/atian25/blog/issues/25

Was this page helpful?
0 / 5 - 0 ratings