2020.06.14 记录
vscode 的 golang 插件最近开始由 golang 官方维护,插件的 debug 功能(尤其是remote debug)还处于不完善的阶段,配置文件最近有过几次改动。不能用的话要多参考下官方文档:
https://github.com/golang/vscode-go/blob/master/docs/debugging.md
下面是目前的最佳实践配置和一些文档相关的解释。
远端启动
这一节是根据我公司内部的项目结构和生产环境配置来的,领会精神即可。重点是下面的本地配置章节。
项目的 docker/debug.dockerfile
里面要这样配置 entrypoint:
1 | ENTRYPOINT ["/dlv", "--log", "--accept-multiclient", "-l=:40000", "--headless=true", "--api-version=2", "exec", "/app"] |
解释:
--accept-multiclient
可以让客户端 dlv 多次连接和断开
--api-version=2
是一定要配置的,否则默认是 1PS:
--continue
参数需要测试,可以让 dlv 启动的时候就运行/app
,目前需要连接一次才会启动
k8s deploy.yml 里需要接的 /app
的参数则是(grpc staging 为例):
1 | - args: |
另外建议 deploy 里把 health check 去掉,内存至少给个 200m。
本地配置
1. vscode 的 luanch.json
1 | { |
详细解释在最下方。
2. 映射 pod 端口到本地
- 应用端口,比如 grpc 为启动时监听的 6000 端口
- dlv 启动时监听的端口 40000
pod 会有 log 显示 dlv 连接、创建断点等等行为
3. 把 go mod 的下载目录软链接到仓库目录
比如我本地默认的 GOPATH 是 ~/go
,默认 go mod 的下载目录是 ~/go/pkg/mod
,那么在仓库根目录(比如 ~/proj/learning
)操作:
1 | mkdir -p .cache/pkg |
这些完成后就可以用 vscode 打断点调试了。
解释
remotePath
这个参数实际上指的是远端运行的二进制在编译时的路径。
比如名为 learning
的项目在我们的 gitlab runner 上编译时,当时路径为 /builds/infra/service/learning
。
这个路径可以在本机
dlv connect 127.0.0.1:40000
后,用sources
命令查看所有包找到(会列出全部的包,需要搜索一下找到)。
映射关系
vscode 会根据 remotePath
参数和本地的仓库目录来计算根目录,映射时去掉不重复的前缀。
2020.06.14 经测试 goland 会很智能的映射文件,但有时还是会出错,比如遇到我们 replace 过的库。
vscode 经过正确映射可以不出错,官方也在尝试加入自动映射文件。
软链接
上面这样配置之后,可以正确映射出项目仓库里的文件,我们可以跳转和打断点到正确的行数。
但是这时 go mod 下载目录里的第三方库的代码是没办法调试的。
这是因为 build 出的二进制会记录代码的位置和行数。比如用到 github.com/shanbay/[email protected]
这个库:
- 在我本地的位置是
~/go/pkg/mod/github.com/shanbay/[email protected]/
- gitlab runner 上 build 镜像时,为了缓存第三方库,所以我们把 GOPATH 配置成了相对路径
.cache
。所以二进制记录的位置是/builds/infra/service/learning/.cache/pkg/mod/github.com/shanbay/[email protected]/
在调试的时候 step in 或者打断点,都会没办法映射到本地的文件。vscode 暂时也没有提供一个参数映射 go mod 位置(但是有人提过了)。
所以我们这里给了一个软链接,软链接之后 learning/.cache/pkg/mod/github.com/shanbay/[email protected]/
目录在本地也存在,所以就能够正常调试了。
标准库同理,我在本地的标准库默认位置是 /usr/local/go/src
,gitlab runner 上 build 时标准库也在这个目录,所以不用软连接也可以正确调试和打断点。
所以远端调试,最方便的方法是在远端运行本地 build 出来的 debug 二进制,这样映射关系不用配置就是正确的。