在vscode中调试nginx源码

NGINX architecture

vscode调试nginx源码

clone源码

  • bash
1
git clone https://github.com/nginx/nginx

除了官方的nginx,也可以考虑用阿里的TengineOpenResty

这两个发行版添加了各自的三方module

编译运行

  1. 修改 /auto/cc/conf 文件,将ngx_compile_opt=”-c” 修改为 ngx_compile_opt=”-c -g”

    -g用来生成调试信息:详见gcc文档

  2. 执行 sudo ./auto/configure –prefix=nginx工程目录 ,如果遇到错误 “the HTTP rewrite module requires the PCRE library”,说明少了用来匹配正则表达式的pcre依赖包,可以自行根据平台进行安装

    • Debein
    • MacOS
    • CentOS
    1
    apt install pcre2-utils
  3. 执行 sudo make

  4. 执行 ./objs/nginx,打开浏览器访问下 127.0.0.1,没问题的话就可以看到Nginx的欢迎界面了。

    nginx

具体源码编译内容可以参考nginx文档

Nginx的多进程架构

nginx是多进程架构:一个Master进程,若干个Worker进程。

Master进程负责管理 Worker 进程,处理nginx命令行指令

Worker进程负责接收处理客户端请求

Worker进程数通常设置成CPU核数,worker_processes: auto;可以自动检查CPU设置成核心数。

Worker进程和redis类似使用单线程+IO多路复用实现高并发处理IO请求。

NGINX architecture

Master进程调试

  1. 修改/conf/nginx.conf

    • nginx
    1
    2
    3
    4
    # 关闭Master守护进程的功能
    daemon off;
    # 便于调试只启动一个Worker进程
    worker_processes 1;

    daemon默认都是on开发阶段关闭

  2. 添加VSCODE调试配置

    • 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
    {
    "version": "0.2.0",
    "configurations": [
    {
    "name": "(gdb) Launch",
    "type": "cppdbg",
    "request": "launch",
    "program": "${workspaceFolder}/objs/nginx",
    "args": [
    "-c",
    "${workspaceFolder}/conf/nginx.conf"
    ],
    "stopAtEntry": false,
    "cwd": "${workspaceFolder}",
    "environment": [],
    "MIMode": "gdb",
    "miDebuggerPath": "/usr/bin/gdb",
    "setupCommands": [
    {
    "description": "Enable pretty-printing for gdb",
    "text": "-enable-pretty-printing",
    "ignoreFailures": true
    }
    ]
    }
    ]
    }

    如果是MacOS,不愿意装gdb,也可以用llvm的lldb进行调试。具体配置可以参考vscode文档

  3. 打断点,Debug起来

    nginx debug

调试Worker进程

  1. 查看 Worker 进程pid

    • bash
    1
    ps aux | grep nginx

    nginx worker process

  2. 编辑launch.json,Attach到worker进程

    • json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
    "version": "0.2.0",
    "configurations": [
    /* ... */
    {
    "name": "(gdb) Attach Worker",
    "type": "cppdbg",
    "request": "attach",
    "program": "${workspaceFolder}/objs/nginx",
    "MIMode": "gdb",
    "miDebuggerPath": "/usr/bin/gdb",
    "processId": "9133"
    }
    ]
    }

    这里的进程id填进去就行了

  3. 切换到Attach Worker

    Attach Worker

  4. 接受请求的地方打个断点,浏览器重新刷新一下,请求就进来了

    Debug Worker Process

  5. 从函数堆栈中,可以看到请求的处理过程

    process request

关闭Nginx多进程模式

启动两个进程的方式debug确实挺麻烦的,nginx提供了配置关闭多进程架构,这样就可以在一个进程里对nginx的整个流程进行debug了,避免上面繁琐的配置。

只需要在nginx.conf文件中把daemonmaster_process设成off即可。

  • nginx
1
2
3
4
# 关闭Master守护进程的功能
daemon off;
# 关闭多进程架构,如果为off,不会启动worker_process进程
master_process off;

ReadMore: https://github.com/agile6v/awesome-nginx

本作品采用 知识共享署名 4.0 国际许可协议 进行许可。

转载时请注明原文链接:https://blog.hufeifei.cn/2021/10/C-C++/vscode-debug-nginx/

鼓励一下
支付宝微信