在nginx负载均衡器中设置跟踪ID

41
我正在使用Nginx作为多个上游应用程序服务器的负载均衡器,并希望设置跟踪ID以将请求与应用程序服务器日志相关联。在Nginx中实现这一点的最佳方法是什么,是否有适用的第三方模块?
否则,一种相当简单的方法是基于时间戳(如果不够准确,可能加上随机数),并将其设置为请求中的额外标头,但我在文档中只看到了用于设置响应标头的set_header命令。
4个回答

109

nginx 1.11.0添加了新变量$request_id,它是一个唯一标识符,因此您可以执行以下操作:

nginx 1.11.0增加了名为$request_id的新变量,该变量具有唯一标识符功能,您可以使用它进行如下操作:

   location / {
      proxy_pass http://upstream;
      proxy_set_header X-Request-Id $request_id;
   }

请参考 http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_id


3
供参考:$request_id的文档在这里 http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_id。 - Andrew Newdigate
$request_id 已经在当前版本的nginx中被弃用和移除。如果有人现在想知道,可以使用 $connection(连接序号)代替。 - Gerald
1
@isapir,反过来了(没检查,抱歉)。$request_id仅在nginx Plus版本1.11中可用:https://docs.nginx.com/nginx/releases/#nginx-plus-release-10-r10 - 对于其他人,请使用此组合:$connection-$connection_requests,它也创建了一个唯一的请求标识符(保持内部子请求相同)。 - Gerald
@isapir - 是啊,我猜是这样的 :D 我们真的应该从顶部开始阅读互联网上的东西吗? - Gerald
如何在请求中未设置 X-Request-Id 时添加它?如果请求头已经有一个请求 ID,我不想将其重置为新的。 - Sisir
显示剩余3条评论

33
在大多数情况下,您不需要定制模块,您可以使用http_core_module中嵌入变量的组合来设置标题,这个组合很可能是唯一的。例如:
  location / {
      proxy_pass http://upstream;
      proxy_set_header X-Request-Id $pid-$msec-$remote_addr-$request_length;
  }

这将生成一个请求ID,如“31725-1406109429.299-127.0.0.1-1227”,应该足够“唯一”,可以用作跟踪ID。


非常好。它能被设置为一个变量以便在请求中重复使用吗?这样它也可以在日志中使用了。否则,调用 $msec 两次将生成不同的值,所以我想到了类似于 set $request_id $pid-$msec-$remote_addr-$request_length; 的东西,但是到目前为止我还无法让它工作。 - isapir
6
对我来说很有效,我正在使用这个 set $tid $pid-$msec-$remote_addr-$request_length-$connection;proxy_set_header X-Tracing-Id $tid; 稍后,请检查您的使用范围。 - sbange
可能不希望泄露$remote_addr,以防用户想公开共享请求ID。 - Justin
如果nginx可以从$pid-$msec-$remote_addr-$request_length中获取md5或sha,则几乎是随机UID,值将是单片的。 - gayavat

14

适用于nginx版本1.3.8、1.2.5及以上的新答案解决了老问题。

现在你可以使用$connection$connection_requests的组合。只需在server块中定义自己的变量:

server {
    ...
    set  $trace_id  $connection-$connection_requests;
    ...
}

此id在nginx中将是唯一的,除非服务器重新启动。

$connection - 连接序列号。这是nginx为每个连接分配的唯一编号。如果在单个连接上收到多个请求,则所有请求将具有相同的连接序列号。序列号在主nginx进程终止时重置,因此它们在较长时间内不会是唯一的。

$connection_requests - 通过此$connection发出的请求次数。

然后,在您的location块中设置实际的跟踪ID:

location / {
    ...
    proxy_set_header X-Request-Id $trace_id;
    ...
}

额外提示: 使$trace_id 在服务器重启后依然唯一:

set  $trace_id  $connection-$connection_requests-$msec;

$msec - 当前的 Unix 时间戳,精确到毫秒(浮点数)。


我在我们的应用程序中使用一个变量作为TRACE_ID。set TRACE_ID $connection-$connection_requests;这个写法对我有效吗?因为使用这个自定义变量时,proxy_set_header对我无效。 - mohit

0
在我们的生产环境中,我们有一个类似这样的自定义模块。它可以生成唯一的跟踪 ID,并将其推送到发送到上游服务器的 HTTP 标头中。上游服务器将检查是否设置了某个字段,如果设置了,则获取该值并将其写入访问日志,因此,我们可以跟踪请求。
我发现一个第三方模块看起来很相似: nginx-operationid,希望它有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接