LoginSignup
71

More than 5 years have passed since last update.

NginxでWebサーバ間をトレースするrequest_id

Last updated at Posted at 2017-04-08

$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の引き継ぎを行うことができます。

x_request_id.conf
# 独自の $_request_id を定義し、設定する
set $_request_id $request_id;
if ($http_x_request_id) {
    set $_request_id $http_x_request_id;
}
nginx.conf
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だけでマイクロサービス間のトレースを行うのがお手軽にできるので良いですね。便利!


  1. もちろん、 X-Request-Id は任意なのでサービスごとにお好きなヘッダ名に変えてもOKです 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71