Nginx 使用requestid 对应用程序日志及性能追踪

问题描述:业务侧经常会遇到一个问题,可以拿到某个慢查询的SQL(比如mysql slowlog, 或是使用的云产品打开实例页面查看对应的慢日志),但是确很难找到对应的业务代码在哪里?(除非SQL本身具有特殊识别性,或是对业务系统非常之熟悉外,如果很雷同的,找起来确实很痛苦,亲测是这样)

针对上面出现的这个问题,nginx request_id 可以完美解决

nginx 从1.11 之后支持生成request_id

部署方案:

1.nginx 接入层关键配置

map $http_x_log_request_id $log_request_id {
    default $http_x_log_request_id;
    -       $request_id;
    ""      $request_id;
}

location ~ .*\.(php|php5)?$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param   LOG_REQUEST_ID $log_request_id;
    include         fastcgi_params;
    fastcgi_intercept_errors on;
    error_page      500 502 503 504  /50x_php.html;
}

2.业务层WEB框架入口代码:设置全局变量

$GLOBALS['LOG_REQUEST_ID'] = !empty($_SERVER['LOG_REQUEST_ID']) ? $_SERVER['LOG_REQUEST_ID'] : $_SERVER['REQUEST_TIME_FLOAT'];

3.业务层JOB框架入口代码:设置全局变量,由于job不经过nginx层,所以request_id自己生成

<?php
$job_request_id = md5("{$script_name}." . microtime(true));
$GLOBALS['LOG_JOB_REQUEST_ID'] = $job_request_id;
?>

4.业务日志收集到文件

<?php
....
$log['controller'] = controller值
$log['action'] = action值
$log['url'] = 当前请求的url, 可以用$_SERVER['REQUEST_URI']获取;
$log['refer'] = //refer, 可以从$_SERVER获取;
$log['user_agent'] = user_agent值,可以从$_SERVER获取;
$log['ip'] = ip获取函数
$log['http_status'] = http状态码,可以从$_SERVER获取;
$log['log_request_id'] = isset($GLOBAL['LOG_REQUEST_ID']) ? isset($GLOBAL['LOG_REQUEST_ID']) : '';
write_log(json_encode($log));
....
?>

5.将第三步写的log导入到es中,便于查询log_request_id对应的请求来源

6.框架SQL执行处代码修改:

$comment_token = '';
if(defined('IS_JOB') && IS_JOB) {
	if(isset($GLOBALS['LOG_JOB_REQUEST_ID']) && !empty($GLOBALS['LOG_JOB_REQUEST_ID'])) {
		$comment_token = '/*job_' . $GLOBALS['LOG_JOB_REQUEST_ID'] . '*/';
	}
} else {
	if(isset($GLOBALS['LOG_REQUEST_ID']) && !empty($GLOBALS['LOG_REQUEST_ID'])) {
		$comment_token = '/*web_' . $GLOBALS['LOG_REQUEST_ID'] . '*/';
	}
}
$sql = $sql . $comment_token;

$this->_result = $this->_execute($sql);

这里在执行的SQL语句后面接上/*request_id*/,并不影响SQL本身的执行,与此同时还能知道SQL的来源,下图为慢日志查询中显示的SQL语句,带上了request_id, 这样是不是就可以得容易知SQL语句来自业务哪了呢?

根据上述步骤1,2,3,4,5,就可以根据慢日志查询的SQL, 反查到对应的业务请求来源了,是不是很帅?