用DTrace pid提供程序调试nginx
本文假设读者对nginx内部和 DTrace 有一般的了解。
虽然使用 –with-debug 选项构建的nginx 已经提供了大量关于请求处理的信息,但是有时候更有必要更详细地跟踪代码路径的特定部分,同时省略其余的调试输出。DTrace pid提供程序(在Solaris,MacOS上可用)是浏览用户程序内部的有用工具,因为它不需要任何代码更改,并且可以帮助您完成任务。跟踪和打印nginx函数调用的简单DTrace脚本可能如下所示:
#pragma D option flowindent
pid$target:nginx::entry {
}
pid$target:nginx::return {
}
尽管如此,功能调用跟踪的DTrace功能仅提供有限的有用信息。功能参数的实时检查通常更有趣,但也更复杂一些。以下示例旨在帮助读者更熟悉DTrace以及使用DTrace分析nginx行为的过程。
使用DTrace与nginx的常见方案之一是:附加到nginx工作进程以记录请求行和请求开始时间。附加的相应函数是 ngx_http_process_request(),而有争议的参数是指向ngx_http_request_t结构的指针。这种请求记录的DTrace脚本可以简单到:
pid$target::*ngx_http_process_request:entry
{
this->request = (ngx_http_request_t *)copyin(arg0, sizeof(ngx_http_request_t));
this->request_line = stringof(copyin((uintptr_t)this->request->request_line.data,
this->request->request_line.len));
printf("request line = %s/n", this->request_line);
printf("request start sec = %d/n", this->request->start_sec);
}
应该注意的是,在上面的例子中,DTrace需要一些关于ngx_http_process_request结构的知识。不幸的是,可以在DTrace脚本中使用特定的#include指令,然后将其传递给C预处理器(带有-C标志),但这并不真正有效。由于很多交叉依赖关系,几乎所有的nginx头文件都必须包含在内。反过来,根据configure脚本设置,nginx头将包括PCRE,OpenSSL和各种系统头文件。在理论上,与特定的nginx构建相关的所有头文件可能都包含在DTrace脚本预处理和编译中,实际上DTrace脚本最有可能由于某些头文件中的未知语法而无法编译。
上述问题可以通过在DTrace脚本中仅包含相关且必要的结构和类型定义来解决。DTrace必须知道结构,类型和字段偏移的大小。因此,通过手动优化用于DTrace的结构定义,可以进一步降低依赖性。
让我们使用上面的DTrace脚本示例,看看它需要正确的结构定义。
首先,由configure生成的objs/ngx_auto_config.h文件应该被包括,因为它定义了一些影响各种各样的常量 #ifdef’s。在此之后,像ngx_str_t,ngx_table_elt_t, ngx_uint_t等一样的一些基本的类型和定义应放在DTrace脚本的开始位置。这些定义是紧凑的,常用的,不太可能经常改变。
在ngx_http_process_request_t结构中包含了很多指向其他结构的指针。因为这些指针与这个脚本无关,而且因为它们具有相同的大小,所以可以用void指针替换它们。而不是更改定义,最好添加适当的typedefs,但是:
typedef ngx_http_upstream_t void;
typedef ngx_http_request_body_t void;
最后但并非最不重要的是添加两个成员结构(ngx_http_headers_in_t, ngx_http_headers_out_t)的定义,回调函数的声明和常量的定义。
最后的DTrace脚本可以从 这里 下载 。
以下示例显示运行此脚本的输出:
# dtrace -C -I ./objs -s trace_process_request.d -p 4848
dtrace: script 'trace_process_request.d' matched 1 probe
CPU ID FUNCTION:NAME
1 4 .XAbmO.ngx_http_process_request:entry request line = GET / HTTP/1.1
request start sec = 1349162898
0 4 .XAbmO.ngx_http_process_request:entry request line = GET /en/docs/nginx_dtrace_pid_provider.html HTTP/1.1
request start sec = 1349162899
使用类似的技术,读者应该能够跟踪其他nginx函数调用。
也可以看看
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/99540.html