内容简介:查一般的 bug,我更习惯直接加打印,能快速定位问题,远比断点调试方便的多。但遇到一些复杂、或是涉及第三方类库时,却不得不需要添加断点逐步跟踪逻辑。使用 golang 开发的微服务,全部是直接运行在 docker 容器里的,想要调试并不是一件简单的事情,这时候我们就需要 Remote Debug (远程调试)
查一般的 bug,我更习惯直接加打印,能快速定位问题,远比断点调试方便的多。但遇到一些复杂、或是涉及第三方类库时,却不得不需要添加断点逐步跟踪逻辑。
使用 golang 开发的微服务,全部是直接运行在 docker 容器里的,想要调试并不是一件简单的事情,这时候我们就需要 Remote Debug (远程调试)
- vscode - 代码编辑器
- ms-vscode.go - vscode 支持 Go 语言的插件
- delve - Golang 调试工具,支持远程调试
- Makefile - 封装指令的合集
- alpine - 迷你 Docker 系统镜像,只有 5MB
启动容器
通过 Makefile
和 Dockerfile
编译镜像和运行 Docker 容器,我的方式是在本地(MacOS)上编译好 Linux 的可执行文件,拷贝到用 alpine 小镜像创建的容器里。也可以选择用 golang 镜像,拷贝源码进去。
-
配置
Makefile
-gcflags "all=-N -l" -security-opt="seccomp=unconfined" --cap-add=SYS_PTRACE -p 20000:20000
NAME := account IMAGE := $(NAME)-service # 编译镜像 build-debug: # 清理废弃的image (按需开启) docker image prune -f # 编译Linux版 dlv可执行文件 GOOS=linux GOARCH=amd64 go build github.com/go-delve/delve/cmd/dlv # 编译Linux版 应用可执行文件 GOOS=linux GOARCH=amd64 go build -gcflags "all=-N -l" # 指定Dockerfile 生成镜像 docker build -f Dockerfile.debug -t $(IMAGE) . # 清理掉生成的可执行文件 rm -f $(NAME) dlv # 运行容器 run-debug: # my-docker-network 是我的Docker network,所有的微服务都在这个网络里,可以直接互连 docker run --rm --name $(IMAGE) \ --network my-docker-network \ --security-opt="seccomp=unconfined" --cap-add=SYS_PTRACE \ -p 20000:20000 \ $(IMAGE) debug: build-debug run-debug
-
配置
Dockerfile.debug
容器启动入口为 ./dlv --listen=:20000 --headless=true --api-version=2 --log=true exec ./account
-
./
代表 WORKDIR 的/app
目录,dlv、account 可执行文件我们通过 Dockerfile 都已经添加到这个目录里了 -
--listen=:20000
dlv 服务绑定的端口 -
--headless=true
调试服务器,无 ui 模式 -
--api-version=2
服务提供的 API 版本 -
--log=true
开启日志,否则只能看到应用日志,没有 dlv 自身的日志 -
exec ./account
准备执行的程序,这个程序必须支持 Debug
与 exec
对应的还有另外一个指令: debug
,直接调试源码可以用
FROM alpine:3.9 # 应用程序需要这个组件来支持请求HTTPS的网址 RUN apk add ca-certificates RUN mkdir /app WORKDIR /app ADD dlv account config.yml ./ ENTRYPOINT ["./dlv", "--listen=:20000", "--headless=true", "--api-version=2", "--log=true", "exec", "./account"]
- 运行容器
会发现没有应用启动日志,是因为微服务在此时还未被拉起,只是关联好了
$ make debug ... 2019-05-08T13:03:23Z info layer=debugger launching process with args: [./account] API server listening at: [::]:20000
Vscode 配置及断点调试
- 配置启动文件
-
mode
remote 开启远程模式 -
host
、port
配置成 dlv 暴露出的服务器地址 -
program
配置成本地对应的源码 main 文件 -
launch.json
{ "version": "0.2.0", "configurations": [ { "name": "Remote Debug", "type": "go", "request": "launch", "mode": "remote", "remotePath": "", "port": 10001, "host": "127.0.0.1", "program": "${workspaceRoot}/cmd/account/main.go", "showLog": true, "env": {}, "args": [] } ] }
- 点击开始调试,应用才开始运行,所以可以看出是 vscode 客户端通知 dlv 服务器启动应用的
- 这时候我们在 vscode 里创建一个断点,服务器会出现对应的日志。
2019-05-08T13:06:03Z debug layer=debugger halting 2019-05-08T13:06:03Z info layer=debugger created breakpoint: ... 2019-05-08T13:06:03Z debug layer=debugger continuing
- 接下来就和在本地调试程序是一样的了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。