【架构】Nginx如何设置X-Request-ID请求头,记录请求时间:毫秒?

Nginx is awesome, but it’s missing some common features. For instance, a common thing to add to access logs is a unique ID per request, so that you can track the flow of a single request through multiple services. Another thing it’s missing is the ability to log request_time in milliseconds, rather than seconds with a millisecond granularity. Using Lua, we can add these features ourselves.

I’ll show the whole solution, then I’ll break it down into parts:

http {
...

        map $host $request_time_ms {
            default ‘‘;
        }
        map $host $uuid {
            default ‘‘;
        }

        lua_package_path ‘/etc/nginx/uuid4.lua‘;
        init_by_lua ‘
            uuid4 = require "uuid4"
            math = require "math"
        ‘;

        log_by_lua ‘
          ngx.var.request_time_ms = math.floor(tonumber(ngx.var.request_time) * 1000)
        ‘;

        log_format mycustomformat ‘[$time_local] "$request" $status $request_length $bytes_sent $request_time_ms $uuid‘;
        access_log /var/log/nginx/access.log mycustomformat;

...
}

server {
...

  set_by_lua $uuid ‘
    if ngx.var.http_x_request_id == nil then
        return uuid4.getUUID()
    else
        return ngx.var.http_x_request_id
    end
  ‘;

...
}

It’s necessary to set variables before we use them in Lua. Using map is a trick to set variables in the http context (you can’t use set $variable ” in http). For the case of uuid, we are going to set it in the server section (during the rewrite context), but in case it’s not set, we want to avoid throwing errors. Here’s how we set these variables:

        map $host $request_time_ms {
            default ‘‘;
        }
        map $host $uuid {
            default ‘‘;
        }

Next we add a uuid4 library to our path, and include the libraries into our context:

        lua_package_path ‘/etc/nginx/uuid4.lua‘;
        init_by_lua ‘
            uuid4 = require "uuid4"
            math = require "math"
        ‘;

Using the log_by_lua function, we’ll set the request_time_ms variable we’ll use in the log_format config. This Lua function is called in the log context, before logs are written, allowing us to make the variables available to it:

        log_by_lua ‘
            ngx.var.request_time_ms = math.floor(tonumber(ngx.var.request_time) * 1000)
        ‘;

Next we set the log format, and use it for the access log:

        log_format mycustomformat ‘[$time_local] "$request" $status $request_length $bytes_sent $request_time_ms $uuid‘;
        access_log /var/log/nginx/access.log mycustomformat;

Lastly, we set the uuid during the rewrite context in the server section, using set_by_lua. To facilitate following a request across services, we’ll reuse the header if it’s already set. If the header isn’t set, then this request didn’t come from another service, so we’ll generate a UUID:

server {
...

  set_by_lua $uuid ‘
    if ngx.var.http_x_request_id == nil then
        return uuid4.getUUID()
    else
        return ngx.var.http_x_request_id
    end
  ‘

...
}

If you’re trusting this header data in any way, you should be sure to filter/restrict that header appropriately so that the client can’t change it.

Update (Thursday December 11 2014): Edited the post to move the uuid generation into the server section and using set_by_lua, so that the uuid can be set to/from the header to flow through the stacks properly. Shout out to Asher Feldman for working out a better solution with me.

参考资料:

Using Lua in Nginx for unique request IDs and millisecond times in logs:http://ryandlane.com/blog/2014/12/11/using-lua-in-nginx-for-unique-request-ids-and-millisecond-times-in-logs/

Simple nginx lua script to add UUID to each request for end to end request tracking:https://gist.github.com/erikcw/e999e1fb438dbbb91533

Is there a way to log a per request unique id for nginx?:http://serverfault.com/questions/580394/is-there-a-way-to-log-a-per-request-unique-id-for-nginx

http://stackoverflow.com/questions/17748735/setting-a-trace-id-in-nginx-load-balancer

https://github.com/kali/nginx-operationid

时间: 2024-10-31 09:22:16

【架构】Nginx如何设置X-Request-ID请求头,记录请求时间:毫秒?的相关文章

request获取请求头和请求数据

1 package cn.itcast.request; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.PrintWriter; 6 import java.lang.reflect.InvocationTargetException; 7 import java.util.Enumeration; 8 import java.util.Map; 9 10 import javax.s

HTTP 请求头与请求体 - 某熊的全栈之路 - SegmentFault

本文从属于笔者的HTTP 理解与实践系列文章,对于HTTP的学习主要包含HTTP 基础.HTTP 请求头与请求体.HTTP 响应头与状态码.HTTP 缓存这四个部分,而对于HTTP相关的扩展与引申,我们还需要了解HTTPS 理解与实践.HTTP/2 基础.WebSocket 基础这些部分.本部分知识点同时也归纳于笔者的我的校招准备之路:从Web前端到服务端应用架构这篇综述. HTTP Request HTTP 的请求报文分为三个部分 请求行.请求头和请求体,格式如图:一个典型的请求消息头域,如下

Django中获取参数(路径,查询,请求头,请求体)

一.通常HTTP协议向服务器传参有几种途径 : 提取URL的特定部分,如/weather/shanghai/2018,可以在服务器端的路由中用正则表达式截取: 查询字符串(query string),形如key1=value1&key2=value2: 请求体(body)中发送的数据,比如表单数据.json.xml: 在http报文的头(header)中. 1.URL中参数的获取 在定义路由URL时,可以使用正则表达式提取参数的方法从URL中获取请求参数,Django会将提取的参数直接传递到视图

HTTP请求行、请求头、请求体以及响应行、响应头、响应体

HTTP请求报文解剖 HTTP Request :HTTP请求 Request Line:请求行 Header:请求头 Request Body:请求体 HTTP请求报文由3部分组成(请求行+请求头+请求体): 下面是一个实际的请求报文: ①是请求方法,HTTP/1.1 定义的请求方法有8种:GET.POST.PUT.DELETE.PATCH.HEAD.OPTIONS.TRACE,最常的两种GET和POST,如果是RESTful接口的话一般会用到GET.POST.DELETE.PUT. ②为请求

第五阶段:JAVAEE 和项目开发(第三课:HTTP的请求头和请求方式)

4. HTTP 协议之请求格式 请求格式的结构:请求行:请求方式.请求的地址和 HTTP 协议版本 请求头:消息报头,一般用来说明客户端要使用的一些附加信息 空行: 位于请求行和请求数据之间,空行是必须的. 请求数据:非必须. 注意: 一张网页的内容是极其丰富的,浏览器会遵循 HTTP 请求的格式将有效数据发送给服务器. 示例(get 请求方式): 示例(post 请求方式): 5. HTTP 协议之请求方式 根据 HTTP 标准,HTTP 请求可以使用多种请求方法. HTTP1.0 定义了三种

IOS - 网络(HTTP请求、同步请求、异步请求、JSON解析数据)

1 // 2 // ViewController.m 3 // IOS_0129_HTTP请求 4 // 5 // Created by ma c on 16/1/29. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "MBProgressHUD+MJ.h" 11 12 @interface ViewController

捕获异常、存sd卡、封装请求头体、加密map值、网络工具类、生成Json、Https协议、传log日志到服务器、app崩溃友好重启

点击打开链接,免积分下载 在集成了统计SDK(友盟统计,百度统计等)之后,有一个非常有利于测试的功能:错误分析!此功能能够将程序在运行中碰到的崩溃(runtimeException)问题反馈到服务器,帮助开发者改善产品,多适配机器.然而在公司android开发中不集成这些SDK,那应该怎么实现这样的功能呢?下面让我们来看下如何使用UncaughtExceptionHandler来捕获异常. 在Android开发中,常常会出现uncheched Exception 导致程序的crash,为了提供良

Android系列之网络(二)----HTTP请求头与响应头

?[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4005034.html 联系方式:[email protected] [正文] 国庆佳节,习惯并享受着一个人独霸整个教研室的感觉. 在上一篇文章中,我们学习到了如何使用HttpClient发送HTTP请求.博文链接: Android系列之网络(一)----使用HttpClient发送HTTP请求

网络请求之GET请求

网络请求-GET请求: 1,NSURL : 请求地址: 2,NSURLRequest : 一个NSURLRequest对象就代表一个请求,它包含的信息有: 1)一个NSURL对象 GET请求,不需要写请求头.请求体,只要告诉请求路径和请求参数就可以了. 2)请求方法 3)请求超时 3,NSMutableURLRequest : NSURLRequest的子类 4,NSURLConnection: 负责发送请求,建立客户端和服务器的连接: NSURLConnection的使用步骤 1,创建一个NS

ios中的ASIHTTPRequest的同步请求和异步请求

1.首先加入ASI开源库 2. WebImageView.h #import <UIKit/UIKit.h> #import "ASIHTTPRequest.h" @interface WebImageView :UIImageView<ASIHTTPRequestDelegate> - (void)setImageURL:(NSURL *)url; @end WebImageView.m #import "WebImageView.h" #