atian25 / blog

天猪部落阁 http://atian25.github.io
1.59k stars 107 forks source link

VSCode 调试 Egg 完美版 - 进化史 #25

Open atian25 opened 6 years ago

atian25 commented 6 years ago

背景

VSCode 早期版本,对 Node Cluster 的调试支持一直不是很友好,譬如:

那些折腾过的历史

黑暗时代

早在 2016 年时就开始的折腾:#14#15 ,没有太好的办法。

青铜时代

然后 @okoala 写了 egg-development-proxyworker

主要思路是在 agent 里面启动一个 socket proxy 来动态代理 worker 的调试端口。 很巧妙的解决了自动重启后调试端口变化问题,但缺点是要开发者手动安装插件,并配置 vscode。

此时只能说达到可用的阶段。

黄金时代

接着,我写了 egg-bin debug 把 proxy 功能内置了,实现原理参见当时的 RFC 提案

并且提供了 vscode-eggjs 扩展来方便配置。

解决了:

对于一般应用开发者基本上已经非常易用了,但还存在以下问题:

而今天,VSCode@1.12.0 正式支持了 Automatically attach debugger to Node.js subprocesses

因此我们之前的做法可以大幅简化了,没解决的问题也基本解决了,可以称为 完美版 了。

完美版的人生

文档已经更新:使用 VSCode 进行调试

安装 vscode-eggjs,并初始化调试配置(如果之前有则需删除 launch.json 文件)

image

然后简单的一个 F5 搞定~

简析

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Egg",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "runtimeExecutable": "npm",
      "windows": { "runtimeExecutable": "npm.cmd" },
      // 启动我们的 egg-bin debug 并默认是 brk
      "runtimeArgs": [ "run", "debug", "--", "--inspect-brk" ],
      // 日志输出到 Terminal,否则启动期的日志看不到
      "console": "integratedTerminal",
      "protocol": "auto",
      // 进程重启后自动 attach
      "restart": true,
      // 因为无需再 proxy,故改回原来的 9229 端口
      "port": 9229,
      // 自动 attach 子进程 
      "autoAttachChildProcesses": true
    }
  ]
}

其他

vscode 扩展生成的配置里面,还支持了单元测试的断点,配置如下:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Egg Test",
      "runtimeExecutable": "npm",
      "runtimeArgs": [
        "run",
        "test-local",
        "--",
        "--inspect-brk"
      ],
      "protocol": "auto",
      "port": 9229,
      "autoAttachChildProcesses": true,
      "disableOptimisticBPs": false,
    }
  ]
}

完美版.最终版1

VSCode 1.22 支持了 Automatically Attach to Node.js processes,也就是如果你开启了这个的话,无需配置什么 launch.json,直接在 terminal 执行 npm run debug --inspect-brk 就会自动 attach 了。

补充

Egg 的调试,跟 Node 没啥区别,因此一定要了解 Node 的基础调试知识。

其中,--inspect-brk 是指在进程第一行就暂停,等待 attach,因此:

上面这几个 attach,由于上面我们提到的 VSCode 的支持,只需要开启配置,即可无感知的一键 attach。 虽然如此,但作为开发者,大家还是需要理解 Node 的调试原理。

atian25 commented 6 years ago

TODO: 补充 egg cluster 背景,重启时消息流向图(messenger, debug)

                  +--------+
                  | Parent |  (egg-scripts/egg-bin)
                  +--------+
                      | 
                      | 
                      v
                  +--------+           +-------+
                  | Master | --------> | Agent |
                  +--------+           +-------+
                 /    |     \
               /      |       \
             /        |         \
           v          v          v
  +----------+   +----------+   +----------+
  | Worker 1 |   | Worker 2 |   | Worker 3 |
  +----------+   +----------+   +----------+
atian25 commented 6 years ago

先删除原有的 .vscode 文件

kapture 2018-02-09 at 11 27 33

zxmajunhong commented 6 years ago

在启动调试之前,我先需要执行npm run debug 吗?

atian25 commented 6 years ago

不需要,你去看下 vscode 自己的调试指南就懂了

my9074 commented 6 years ago

@atian25 我安装了 vscode-eggjs 在 DEBUG 模式,没有对应的 EGG 选项。 环境都是最新版的。 mar-28-2018 16-03-02

atian25 commented 6 years ago

vscode 的激活时机好像有问题,你试下随便打开一个 js,输入下 egg

image

能看到这个的话,再回去调试页面看看

my9074 commented 6 years ago

@atian25 EGG 选项出来了,但是 configurations 是空的。 mar-28-2018 16-48-46

atian25 commented 6 years ago

那可能是 vscode 这块的 API 变了。 手动拷贝下我上面贴的 config 吧

shepherdwind commented 6 years ago

npm run test-local 支持测试单个文件吗?

atian25 commented 6 years ago

支持, npm run test-local -- --grep= 支持所有的 mocha 参数,可以看下 egg-bin 的 READM

atian25 commented 6 years ago

或者 npx egg-bin test --grep=

atian25 commented 6 years ago

VSCode 1.22 新增 Auto Attach 功能,在 Terminal 里面 npm run debug 后,会自动 attach,不需要你 F5 或上面那堆 launch.json 配置啥的

caohongtao commented 6 years ago

imageEgg Debug启动的时候,会报This socket has been ended by the other party错误。昨天升级新vscode后出现的。 然而,先手动执行egg-bin debug,然后使用Egg Attach to remote,可以正常attach上去。

atian25 commented 6 years ago

vscode 新版的 bug,暂时还没时间看,需要跟 vscode 那边反馈

wangtao0101 commented 6 years ago

vscode 新版无法调试,先手动执行egg-bin debug,然后使用Egg Attach to remote,虽然正常attach上去了,但是无法打断点。。。

wangtao0101 commented 6 years ago

@caohongtao 你是用的typescript吗?attach后能打断点吗?

shyser commented 6 years ago

几个月以来我都是用的下面这套配置,包括最近的ts版本,调试体验良好。 也试过最新的官方推荐配置和Auto Attach 方式,都不太好用。本着有保底的办法、外加偷懒的心态,也就没深究了😅。 这个配置其实就是之前某个版本的eggjs vscode插件的配置写法,有需要的同学可以参考一下,希望有帮助。

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Egg Debug",
      "runtimeExecutable": "npm",
      "runtimeArgs": [
        "run",
        "debug"
      ],
      "console": "integratedTerminal",
      "restart": true,
      "protocol": "auto",
      "port": 9999
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Egg Debug with brk",
      "runtimeExecutable": "npm",
      "runtimeArgs": [
        "run",
        "debug",
        "--",
        "--inspect-brk"
      ],
      "protocol": "inspector",
      "port": 9229
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Egg Test",
      "runtimeExecutable": "npm",
      "runtimeArgs": [
        "run",
        "test-local",
        "--",
        "--inspect-brk"
      ],
      "protocol": "auto",
      "port": 9229
    },
    {
      "type": "node",
      "request": "attach",
      "name": "Egg Attach to remote",
      "localRoot": "${workspaceRoot}",
      "remoteRoot": "/usr/src/app",
      "address": "localhost",
      "protocol": "auto",
      "port": 9999
    }
  ]
}
shepherdwind commented 6 years ago

赞,我这边好像需要 npm run debug,然后手动点击一下 Egg Attach to remote 才行

yaojijiayou commented 6 years ago

会出现 image

//----下面这个问题我也遇到了。。------------------------- 手动执行egg-bin debug,然后使用Egg Attach to remote,虽然正常attach上去了,但是无法打断点。。。

xingyesh commented 6 years ago

npm run debug,然后使用vscode Egg Attach to remote 可以。但是真的很容易断开啊,随便改的东西就需要重新执行

atian25 commented 6 years ago

你连接 9999 端口就不会断了

atian25 commented 6 years ago

等会 egg-cluster 这个 PR 合并发布后,就可以解决了。

vscode 最新版对 --debug-port 不再支持了,8.x 后换为 --inspect-port

PS: 最近较忙,其实这种问题,遇到的同学,提炼一个最小可复现案例,跟 vscode 一反馈,早就能解决了。 https://github.com/Microsoft/vscode/issues/49865 就这么简单。

wxfred commented 6 years ago

--debug-port没找到在哪,我看了一下你提交给微软的那个链接,发现--debug-port是写在代码里的是吧?我也不确定,也不知道在哪改,然后只能用npm更新到最新的eggjs,启动调试后没有那个错误弹窗了,但是无法成功启动。我的sequelize初始化成功了,没更新egg前会在sequelize这些初始化前弹窗然后卡死。

PS G:\Nodejs Development\Project> cd 'g:\Nodejs Development\Project'; & 'C:\Program Files\nodejs\npm.cmd' 'run' 'debug' '--' '--inspect-brk'

Project@1.0.0 debug G:\Nodejs Development\Project egg-bin debug "--inspect-brk"

Debugger listening on ws://127.0.0.1:9229/97b90d18-5e76-4a7c-a9de-25d3d047b4d5 For help see https://nodejs.org/en/docs/inspector Debugger attached. 2018-05-16 14:16:51,847 INFO 22160 [master] node version v8.11.1 2018-05-16 14:16:51,850 INFO 22160 [master] egg version 2.8.1 Debugger listening on ws://127.0.0.1:5800/337d2144-61ce-4263-82d4-71cd9ae3ddfb For help see https://nodejs.org/en/docs/inspector Debugger attached. sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules\sequelize\lib\sequelize.js:242:13 2018-05-16 14:16:55,586 INFO 10620 [model] SELECT 1+1 AS result (7ms) 2018-05-16 14:16:55,589 INFO 22160 [master] agent_worker#1:10620 started (3730ms) Debugger listening on ws://127.0.0.1:9230/ea613009-c647-4a6f-98cf-d14d76c6746d For help see https://nodejs.org/en/docs/inspector 9230 opened Debug Proxy online, now you could attach to 9999 without worry about reload. DevTools → chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=tru e&ws=127.0.0.1:9999/__ws_proxy__ Debugger attached. sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules\sequelize\lib\sequelize.js:242:13 2018-05-16 14:16:58,876 INFO 12060 [model] SELECT 1+1 AS result (0ms) 2018-05-16 14:16:59,856 ERROR 12060 nodejs.ECONNREFUSEDError: connect ECONNREFUSED 127.0.0.1:6379 at Object._errnoException (util.js:1022:11) at _exceptionWithHostPort (util.js:1044:20) at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1198:14) code: 'ECONNREFUSED' errno: 'ECONNREFUSED' syscall: 'connect' address: '127.0.0.1' port: 6379 name: 'ECONNREFUSEDError' pid: 12060 hostname: DESKTOP-6GQG52D // 然后一直重复 ECONNREFUSEDError

atian25 commented 6 years ago

ECONNREFUSEDError 明显是你的数据库配置地址不对。

egg-cluster 已经发布了,升级安装下依赖即可

hey, please retry after reinstall dependencies and please never lock it.

$ # reinstall deps and never lock it.
$ rm -rf node_modules yarn.lock package-lock.json
$ npm i --no-package-lock
wxfred commented 6 years ago

@atian25 非常感谢你及时的回复。sequelize没问题,原因是没开启redis服务o(╥﹏╥)o

shiyun commented 6 years ago

请问,node_modules里的模块为什么有时候可以打断点,有时候不行?

atian25 commented 6 years ago

@shiyun 是不是跟加载时机有关?如果你用最新的方式的话,应该是有 --inspect-brk 的,这样的话应该是可以断点到的。

shiyun commented 6 years ago

@atian25 是用的最新的方式,用--inspect断点不到,后面改成--inspect-brk也样断点不到,问了好几个朋友都遇到这样的问题,没找到解决办法。 提示信息是: "未验证的断点,已设置断点但还未绑定"

atian25 commented 6 years ago

@shiyun 你是用 cnpm 的么?刚跟 vscode 那边的人交流了,好像是软链方式会导致他们找不到,已经提 issue 待修复,着急的话先换回 npm

Updated: 如果要 debug 启动期的代码,换回 npm 方式即可。

https://github.com/Microsoft/vscode/issues/51588

yuu2lee4 commented 6 years ago

调试配置里面 没有egg ,在js里输入egg,再去调试配置里就有了,但是生成的config为空,npm run debug后没有自动attach,环境: vscode: 1.25.1 os: macos10.13.6 yarn: 1.5.1 node: 10.7.0 typescript: 3.0.1

atian25 commented 6 years ago

@yuu2lee4 直接复制文档中那段即可

galleonsZcc commented 6 years ago

刚安装的,debug配置项里没有egg,js里输入egg也没有任何的关联。。然后把vs安装了最新版,还是没有用,需要配置什么吗?

~ 试了下,js里还是没有开启联想,但是选择node的debug环境并手动复制config进去,还是可以跑。 那这个插件好像跟没装一样了。。

hhhluke commented 6 years ago

vscode同时起两个egg调试服务的时候,9229端口会冲突啊,我改了端口,没有用?

atian25 commented 6 years ago

@galleonsZcc 你先直接拷贝文档里面的就好了,vscode 那边升级了,旧的方式不行了,我晚点修复下。

@dryqiao 你要改两个的,一个是 npm run debug -- --inspect-brk=端口号,然后再改那个 port 的。(一个是告诉 node 在指定端口调试,一个是告诉 vscode 去连接这个端口)

IEfucker commented 6 years ago

谢谢@StephenSeraph ,你的代码Egg Debug配置有效,Egg Debug with brk配置和当前版本的vscode-eggjs配置一样,用不了。是vscode的bug?

请教请教大神@atian25 些问题, 1.vscode-eggjs生成的配置runtimeArgs里,"--" 是什么,空的参数吗 2.另外看到brk的解释是:Break before user code starts,这种说的是什么使用场景 3.attach和launch的使用场景也不理解,何种情况使用哪种 4.我看启动后的log很多,但看不懂是什么意思,是不是启动成功了,或者是否按照想要的方式启动的也不能判断,能帮忙解释下log吗(前两天用vscode-eggjs的默认配置启动debug总是失败,但没有失败提示)

atian25 commented 6 years ago

@IEfucker

vscode-eggjs生成的配置runtimeArgs里,"--" 是什么,空的参数吗

看我这篇回答: https://www.zhihu.com/question/267095526/answer/318608937

attach和launch的使用场景也不理解,何种情况使用哪种

debug 其实是 2 个操作:

另外看到brk的解释是:Break before user code starts,这种说的是什么使用场景

指的是在 Node 的第一行就断点,而不是等开发者 attach,也就是上面那个问题合成一步,从而可以断点到两步之间的一些逻辑。

shmilyoo commented 5 years ago

vscode同时起两个egg调试服务的时候,9229端口会冲突啊,我改了端口,没有用?

@galleonsZcc 你先直接拷贝文档里面的就好了,vscode 那边升级了,旧的方式不行了,我晚点修复下。

@dryqiao 你要改两个的,一个是 npm run debug -- --inspect-brk=端口号,然后再改那个 port 的。(一个是告诉 node 在指定端口调试,一个是告诉 vscode 去连接这个端口)

同时修改两个端口后,又会报Starting inspector on 127.0.0.1:5800 failed: address already in use

atian25 commented 5 years ago

https://github.com/eggjs/egg-cluster/blob/master/lib/master.js#L191

配置下环境变量

bell8910 commented 5 years ago

@atian25 感谢提供配置,可以在vscode调试eggjs了,vscode用的最新版1.28.2

package.json 增加

"scripts": {
    "debug": "egg-bin debug"
  }

launch.json在configurations里增加

{
      "name": "Launch Egg",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "runtimeExecutable": "npm",
      "windows": { "runtimeExecutable": "npm.cmd" },
      // 启动我们的 egg-bin debug 并默认是 brk
      "runtimeArgs": [ "run", "debug", "--", "--inspect-brk" ],
      // 日志输出到 Terminal,否则启动期的日志看不到
      "console": "integratedTerminal",
      "protocol": "auto",
      // 进程重启后自动 attach
      "restart": true,
      // 因为无需再 proxy,故改回原来的 9229 端口
      "port": 9229,
      // 自动 attach 子进程 
      "autoAttachChildProcesses": true
}
calpa commented 5 years ago

感谢提供调试配置。

我试了一下利用 ts + egg.js 的组合,然后只需要简单npm run debug 命令就行。再简单一点就是按 npm-scripts里面的 debug,达到一键开始 debug 之旅。

jyfcrw commented 5 years ago

请问在WSL里执行 npm run debug,再通过 chrome devtools 调试有试过吗?我遇到的问题是无法命中egg项目里自己写的代码的断点。chrome 70, egg 2.10.0, node 10.5.0

atian25 commented 5 years ago

按我的判断跟 egg 本身关系不大。这种只能自己排查,跟环境有关。但只要你对 devtools 断点有理解,一般查起来很快。

  1. 试着删除目录,再重新安装依赖,不要锁版本。

hey, please retry after reinstall dependencies and please never lock it.

$ # reinstall deps and never lock it.
$ rm -rf node_modules yarn.lock package-lock.json
$ npm i --no-package-lock
  1. 然后看下 debug 的日志输出,看看 debug 端口都是哪几个

  2. 然后你的 chrome devtool 去 attach 这几个看看。(或者用 vscode 的 attach 功能试试)

xiabaiyang commented 5 years ago

@shiyun node_modules 里的模块 debugger 的问题你解决了吗?

mistypig commented 5 years ago

今天vscode推送了1.32.1版本,升级以后Debug会卡住。去掉--inspect-brk可以启动成功,但无法打断点,报Breakpoint set but not yet bound。

—————————————— 手动打开auto attach解决了。

atian25 commented 5 years ago

@mistypig 我无法复现。

另外,如果你不需要在启动期断点的话,其实可以不用加 --inspect-brk 的。

Version 1.32.1 (1.32.1)

image

debug

atian25 commented 5 years ago

@mistypig https://github.com/eggjs/egg/issues/3534#issuecomment-471857293

shen-lan commented 5 years ago

如何忽略进入node_module文件夹?

atian25 commented 5 years ago

请大家务必务必注意,现在的调试,就是 Node 自己的多进程调试,egg 并没有做什么处理。所以,大部分的问题,需要你们了解 VSCode 和 Node 本身在调试这块的知识。

atian25 commented 5 years ago

更新下最新的一些信息:

  1. 单元测试那个,需要加一个 "disableOptimisticBPs": false, 才能正确的在 test 文件中断点。https://github.com/Microsoft/vscode/issues/37199
  2. WebStorm 2019 后, DEBUG_NODE_OPTIONS 这个变量丢失了,不过还是目前看来是不影响断点。
atian25 commented 5 years ago

如何忽略进入node_module文件夹?

https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_skipping-uninteresting-code-node-chrome