envoy 是目前高性能数据平面的基本标准了,虽然有些看着笨重,但是社区牛逼,其次性能也很高,目前大部分公司的mesh基本都是通过envoy构建的,所以学习是很重要的,本人主要是介绍如何debug envoy,本人也是踩坑了大半天!
背景
envoy 是目前高性能数据平面的基本标准了,虽然有些看着笨重,但是社区牛逼,其次性能也很高,目前大部分公司的mesh基本都是通过envoy构建的,所以学习是很重要的,本人主要是介绍如何debug envoy,本人也是踩坑了大半天!
C++的代码最难的就是主流的IDE工具对代码阅读、调试难度比较大,这几本就挡住了大部分人的学习动力,其中clion对于cmake支持度很好,vscode是比较方便和灵活,可以远程直接debug,一般debug c++的流程就是先要编译成一个二进制产物,通过 gdb/lldb 进行debug。envoy 默认在linux上构建是用clang编译的,debug的话最好用lldb!
环境
- 本地开发环境是 Mac
- 远程开发环境是 Linux(Debian10, 8C+16G, 公司有32c+64g的啥时候我申请个,真的是不好意思😬)【如果你本地机器性能高可以不用远程,直接本地起个docker就行了】
- 编译环境是远程的Docker (vscode remote 也在这里运行)
- envoy - v1.26.0 (构建环境是 clang/lldb 14.0.0,clang比gcc构建要快很多….)
- 本地 vscode
注意:
envoy这种大型项目它对于环境依赖太重了,所以千万别用本地环境去构建,基本行不通!
c++ debug对于环境一致性要求很高
我本来想试试 lldbserver/gdbserver 用 clion 进行 remote debug,发现人家产物1.4个G,下载elf太墨迹了,所以还是直接在docker容器内调试算了
调试流程
修改脚本
run_envoy_docker.sh
- 配置 http代理,不然拉代码太墨迹了,自己找http/https代理
- 配置docker run 添加参数
--cap-add=SYS_PTRACE --security-opt seccomp=unconfined
支持调试 - docker 最好限制下 cpu,防止编译把电脑cpu打满了,直接挂了!
- 修改bazel cache的挂载目录:
DEFAULT_ENVOY_DOCKER_BUILD_DIR=${HOME}/.cache/bazel_docker
(默认是在/temp 目录下重启电脑就没了)
build_setup.sh
脚本注释掉 (防止把构建产物给删了)
1 2
| #cleanup #trap cleanup EXIT
|
3.do_ci.sh
注释掉 bazel_binary_build 的一些内容
进入容器
1
| ./ci/run_envoy_docker.sh '/bin/bash'
|
构建
执行./ci/do_ci.sh bazel.debug.server_only
即可, 首次构建基本上得两个小时左右,后面增量构建基本上2分钟左右!
1 2
| # 这里可以看到 --config=libc++ 实际上就是clang /usr/local/bin/bazel --output_user_root=/build/tmp/output build --verbose_failures --experimental_generate_json_trace_profile --test_output=errors --repository_cache=/build/repository_cache --experimental_repository_cache_hardlinks --action_env=CLANG_FORMAT --test_tmpdir=/build/tmp --config=libc++ --remote_download_toplevel -c dbg //source/exe:envoy-static
|
最后自己把 cache 文件压缩一下,备份一份,防止手残给删了。。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| envoybuild@a66c8f90a687:/source$ ls -al bazel-bin/source/exe/ total 1381592 drwxrwxrwx 4 envoybuild envoybuild 4096 Aug 19 15:05 . drwxrwxrwx 6 envoybuild envoybuild 4096 Aug 19 13:18 .. -r-xr-xr-x 1 envoybuild envoybuild 56844 Aug 19 13:18 envoy_common_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 2096 Aug 19 13:18 envoy_main_common_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1954 Aug 19 13:18 envoy_main_entry_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1413995968 Aug 19 15:05 envoy-static -r-xr-xr-x 1 envoybuild envoybuild 632368 Aug 19 10:40 envoy-static-2.params drwxrwxr-x 3 envoybuild envoybuild 4096 Aug 19 15:03 envoy-static.runfiles -r-xr-xr-x 1 envoybuild envoybuild 141 Aug 19 10:41 envoy-static.runfiles_manifest -r-xr-xr-x 1 envoybuild envoybuild 3546 Aug 19 13:18 main_common_lib.cppmap drwxrwxr-x 8 envoybuild envoybuild 4096 Aug 19 15:04 _objs -r-xr-xr-x 1 envoybuild envoybuild 1501 Aug 19 14:36 platform_header_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1613 Aug 19 13:18 platform_impl_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1803 Aug 19 14:36 platform_impl_lib_linux.cppmap -r-xr-xr-x 1 envoybuild envoybuild 2275 Aug 19 13:18 process_wide_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1264 Aug 19 13:18 scm_impl_lib.cppmap -r-xr-xr-x 1 envoybuild envoybuild 1863 Aug 19 13:18 terminate_handler_lib.cppmap
|
调试
envoy 核心用的libevent,所以大量回掉代码,阅读调试比较困难!
- 支持调试本地代码
- 支持调试依赖代码
- 本地下载 vscode 插件
- Remote - SSH 可以连接远程虚拟机
- Dev Containers 连接连接服务器内的docker容器
远程连接后下载vscode插件 CodeLLDB
配置 /.vscode/launch.json
文件中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "Launch", "program": "/source/bazel-bin/source/exe/envoy-static", "args": [], "cwd": "/source", "sourceMap":{ "/proc/self/cwd": "/source", "/proc/self/cwd/external": "/build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy/external", } } ] }
|
- 挂载点是,自行查看自己的挂载点 bazel-source 目录就是bazel的构建目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| envoybuild@82990b41dce5:/source$ ls -al total 464 drwxr-xr-x 29 envoybuild envoybuild 4096 Aug 19 10:08 . drwxr-xr-x 1 root root 4096 Aug 19 10:23 .. drwxr-xr-x 9 envoybuild envoybuild 4096 Aug 19 05:23 api -rw-r--r-- 1 envoybuild envoybuild 6 Aug 19 05:23 API_VERSION.txt drwxr-xr-x 3 envoybuild envoybuild 4096 Aug 19 05:23 .azure-pipelines -rw-r--r-- 1 envoybuild envoybuild 2298 Aug 19 05:23 BACKPORTS.md drwxr-xr-x 8 envoybuild envoybuild 4096 Aug 19 05:23 bazel lrwxrwxrwx 1 envoybuild envoybuild 86 Aug 19 06:08 bazel-bin -> /build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy/bazel-out/k8-dbg/bin drwxr-xr-x 2 envoybuild envoybuild 4096 Aug 19 05:23 .bazelci -rw-r--r-- 1 envoybuild envoybuild 152 Aug 19 05:23 .bazelignore lrwxrwxrwx 1 envoybuild envoybuild 75 Aug 19 06:08 bazel-out -> /build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy/bazel-out -rw-r--r-- 1 envoybuild envoybuild 19921 Aug 19 05:23 .bazelrc lrwxrwxrwx 1 envoybuild envoybuild 65 Aug 19 06:08 bazel-source -> /build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy lrwxrwxrwx 1 envoybuild envoybuild 91 Aug 19 06:08 bazel-testlogs -> /build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy/bazel-out/k8-dbg/testlogs -rw-r--r-- 1 envoybuild envoybuild 6 Aug 19 05:23 .bazelversion -rw-r--r-- 1 envoybuild envoybuild 1454 Aug 19 05:23 BUILD
|
- 调试官方demo https://www.envoyproxy.io/docs/envoy/latest/start/quick-start/run-envoy
1
| wget https://www.envoyproxy.io/docs/envoy/latest/_downloads/92dcb9714fb6bc288d042029b34c0de4/envoy-demo.yaml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "Launch", "program": "/source/bazel-bin/source/exe/envoy-static", "args": [ "-c", "/source/envoy-demo.yaml" ], "cwd": "/source", "sourceMap":{ "/proc/self/cwd": "/source", "/proc/self/cwd/external": "/build/tmp/output/b570b5ccd0454dc9af9f65ab1833764d/execroot/envoy/external", } } ] }
|
- 调试, 浏览器可以打开
http://localhost:10000/
(vscode yyds 支持转发端口)
bazel 基本用法
- 这里我用的clang,不太喜欢用gcc, bazel的话直接下载 https://github.com/bazelbuild/bazelisk ,他可以自动下载对应的bazel版本,根据项目里的
.bazelversion
1 2 3 4 5
| ~ which clang++ /usr/lib/llvm-13/bin/clang++
~ which bazel # https://github.com/bazelbuild/bazelisk/releases /home/fanhaodong.516/go/bin/bazel
|
- 脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .PHONY: fastbuild optbuild debug clean
all: fastbuild
fastbuild: # 快速构建 bazel build --config clang //:main
optbuild: # 优化构建 bazel build --config clang -c opt //:main bazel build --config clang -c opt //:main.dwp ls -al bazel-bin/
clean: # 清理bazel此项目的构建缓存 bazel clean
debug: # debug构建, --subcommands 可以查看构建参数,非常有用排查问题。 make debug 2>&1 | tee out.log rm -rf bazel-bin bazel build --config clang -c dbg //:main --subcommands bazel build --config clang -c dbg //:main.dwp --subcommands ls -al bazel-bin/
|
.bazelrc
文件配置构建参数
1 2 3 4 5 6
| build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 build:linux --features=per_object_debug_info build:linux --fission=dbg,opt
build:clang --config=linux build:clang --action_env=CC=clang --action_env=CXX=clang++
|
.bazelversion
配置bazel版本
- CodeLLDB 配置 lldb脚本
.vscode/launch.json
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| { "version": "0.2.0", "configurations": [ { "type": "lldb", // 下同 "request": "custom", "name": "Custom launch", "targetCreateCommands": [ "target create /home/fanhaodong.516/go/src/github.com/anthony-dong/bazel_simple/bazel-bin/main", "setting append target.source-map /proc/self/cwd /home/fanhaodong.516/go/src/github.com/anthony-dong/bazel_simple", "setting append target.source-map /proc/self/cwd/external /home/fanhaodong.516/.cache/bazel/_bazel_fanhaodong.516/a3fbbe1bc80076bc1aaa5a9834db2f5d/execroot/bazel_simple/external" ], "processCreateCommands": [ "settings set target.run-args 1 '2 3' '4 5'", "process launch" ] }, { "type": "lldb", "request": "launch", "name": "Launch", "program": "/home/fanhaodong.516/go/src/github.com/anthony-dong/bazel_simple/bazel-bin/main", // 执行文件路径 "args": [ // 配置执行文件启动参数 "ls", "-al" ], "cwd": "/home/fanhaodong.516/go/src/github.com/anthony-dong/bazel_simple", // 代码路径 "sourceMap": { "/proc/self/cwd": "/home/fanhaodong.516/go/src/github.com/anthony-dong/bazel_simple", // 文件map,第一个必须(bazel在linux下构建 PWD=/proc/self/cwd,强制的) "/proc/self/cwd/external": "/home/fanhaodong.516/.cache/bazel/_bazel_fanhaodong.516/a3fbbe1bc80076bc1aaa5a9834db2f5d/execroot/bazel_simple/external", // 次要配置,看看你需不需要debug依赖,可以配置多个 } } ] }
|
bazel - fission模式
这个比较坑,需要深入了解下,不然debug的话会是噩梦,可以自己写个小项目试试!
- bazel 构建模式:https://bazel.build/docs/user-manual#compilation-mode , 默认是fastbuild
- bazel 调试模式:https://bazel.build/docs/user-manual#strip
1 2
| # 还可以手动再精简 。。。 strip bazel-bin/main -o ./main
|
- fission 模式 https://bazel.build/docs/user-manual#fission
1 2 3 4 5
| # --features=per_object_debug_info 可选可不选了现在 (我的版本是 6.x) # fission 支持 dbg,opt,fastbuild,yes(all),no(none) # 只有开启了 fission 才能够支持 bazel build //:xxx.dwp build:linux --features=per_object_debug_info build:linux --fission=dbg,opt
|
- 构建文件
1 2 3
| bazel build --config clang -c dbg //:main # 没开启 fission 这个执行了也没啥用... //:xxx.dwp 只在开启fission下生效 bazel build --config clang -c dbg //:main.dwp
|
- 未开启 fission (dbg) 构建
1 2 3 4 5 6 7 8 9 10
| drwxr-xr-x 5 fanhaodong.516 fanhaodong.516 4096 Aug 19 22:56 . drwxr-xr-x 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 22:56 .. drwxrwxrwx 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 22:56 external -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 1274544 Aug 19 22:56 main -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 3513 Aug 19 22:56 main-2.params -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 674 Aug 19 22:56 main.cppmap -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 0 Aug 19 22:56 main.dwp drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 22:56 main.runfiles -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 162 Aug 19 22:56 main.runfiles_manifest drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 22:56 _objs
|
- 开启 fission (opt) 明显能看出来可执行文件大小降低了不少 1274544 -> 396626
1 2 3 4 5 6 7 8 9 10 11 12
| ls -al bazel-bin/ total 1676 drwxr-xr-x 5 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 . drwxr-xr-x 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 .. drwxr-xr-x 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 external -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 396626 Aug 19 23:00 main -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 3411 Aug 19 23:00 main-2.params -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 674 Aug 19 23:00 main.cppmap -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 1285592 Aug 19 23:00 main.dwp drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 main.runfiles -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 162 Aug 19 23:00 main.runfiles_manifest drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 _objs
|
- 开启fission (dbg) 1274544 -> 834808
1 2 3 4 5 6 7 8 9 10 11
| total 1808 drwxr-xr-x 5 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 . drwxr-xr-x 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 .. drwxr-xr-x 4 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 external -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 834808 Aug 19 23:00 main -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 3529 Aug 19 23:00 main-2.params -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 674 Aug 19 23:00 main.cppmap -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 980664 Aug 19 23:00 main.dwp drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 main.runfiles -r-xr-xr-x 1 fanhaodong.516 fanhaodong.516 162 Aug 19 23:00 main.runfiles_manifest drwxr-xr-x 3 fanhaodong.516 fanhaodong.516 4096 Aug 19 23:00 _objs
|
- 总结 最好别开,支持度不太好,所以看到
--fission 参数
或者 bazelrc
文件中配置了,请立马注释掉关闭了!!!
bazel - .bazelrc
一旦修改这个文件就得重新构建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| # 配置c++版本 build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14
# 配置 build 的构建参数(当config为linux时) # 可以看上面解释 build:linux --features=per_object_debug_info # build:linux --fission=dbg,opt build:linux --fission=no
# --config=linux 继承配置linux的,可以配置多个 --config 。 build:clang --config=linux
# config=clang时 cc/gcc 为 clang / clang++ # --action_env 主要clang 构建时传递的env参数 build:clang --action_env=CC=clang --action_env=CXX=clang++ # 可配可不配吧,假如clang路径下有ld.lld既不需要配置 # build:clang --linkopt=-fuse-ld=lld
# config=gcc的构建 build:gcc --action_env=CC=gcc --action_env=CXX=g++
|
参考