$request_id
Nginx 1.11.0 以降に限りますが、リクエスト毎に発番されるIDの変数として $request_id が追加されたようです。
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_id
この変数を利用することにより、Nginxコアだけでサービス間のトレースを簡単に行うことが可能になります。
シンプルな例
以下のように、$request_idをログに含めるだけでリクエスト毎のIDを記録できます。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$request_id"';
access_log logs/access.log main;
# クライアントにも返しておくと調査が楽ですね
#add_header X-Request-ID $request_id;
プロキシ先でもリクエストIDを引き継ぎたい
プロキシした先にもrequest_idを渡すことにより、同一リクエストかどうかを判別することが可能になります。
プロキシヘッダにX-Request-Id1 を付与し、それをプロキシ先でも読み取るには以下のような設定になります。
プロキシ先ではカスタムヘッダーの変数である $http_x_request_id を参照しています。
###########################################
# プロキシ元 nginx
###########################################
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$request_id"';
access_log logs/access1.log main;
server {
listen 80;
location / {
proxy_pass http://backend/;
proxy_set_header X-Request-ID $request_id;
}
}
}
###########################################
# プロキシ先 nginx
###########################################
http {
# http_x_request_id を記録する
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$http_x_request_id"';
access_log logs/access2.log main;
server {
listen 80;
location / {
# ...
}
}
}
プロキシ先でもリクエストIDを引き継ぎつつ、設定も共通化したい
ただ、プロキシ元とプロキシ先で設定変えるのは少し面倒ですね。
そこで X-Request-Idが渡ってきたときにはそちらを優先し、なければ $request_idを参照する という処理を共通化してしまえばどの環境でも同一設定かつ、request_idの引き継ぎを行うことができます。
# 独自の $_request_id を定義し、設定する
set $_request_id $request_id;
if ($http_x_request_id) {
set $_request_id $http_x_request_id;
}
http {
# $_request_id を参照する
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$_request_id"';
server {
listen 80;
include ../conf.d/x_request_id.conf;
access_log logs/access1.log main;
# ...
}
}
動作するフルのconfigはgistに置いてあります。
https://gist.github.com/toritori0318/2dc2b64ff696822b02d202bf1fc2f5b2
上記を実行してみたところ、request_id が問題なく引き継ぎ出来ています!
$ tail -1 logs/access1.log
127.0.0.1 - - [08/Apr/2017:16:13:25 +0000] "GET / HTTP/1.1" 200 44 "-" "curl/7.47.1" "-" "8e77df77bdec1eef154d5f819596cb0e"
$ tail -1 logs/access2.log
127.0.0.1 - - [08/Apr/2017:16:13:25 +0000] "GET /fake HTTP/1.1" 200 44 "-" "curl/7.47.1" "-" "8e77df77bdec1eef154d5f819596cb0e"
Nginxだけでマイクロサービス間のトレースを行うのがお手軽にできるので良いですね。便利!
-
もちろん、
X-Request-Id
は任意なのでサービスごとにお好きなヘッダ名に変えてもOKです ↩