【架构】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
【架构】Nginx如何设置X-Request-ID请求头,记录请求时间:毫秒?的更多相关文章
- request获取请求头和请求数据
package cn.itcast.request; import java.io.IOException; import java.io.InputStream; import java.io.Pr ...
- HTTP 请求头与请求体 - 某熊的全栈之路 - SegmentFault
本文从属于笔者的HTTP 理解与实践系列文章,对于HTTP的学习主要包含HTTP 基础.HTTP 请求头与请求体.HTTP 响应头与状态码.HTTP 缓存这四个部分,而对于HTTP相关的扩展与引申,我 ...
- 【转载】HTTP 请求头与请求体
原文地址: https://segmentfault.com/a/1190000006689767 HTTP Request HTTP 的请求报文分为三个部分 请求行.请求头和请求体,格式如图:一个典 ...
- HttpServletRequest对象,请求行、请求头、请求体
HttpServletRequest 公共接口类HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象.对 ...
- Django中获取参数(路径,查询,请求头,请求体)
一.通常HTTP协议向服务器传参有几种途径 : 提取URL的特定部分,如/weather/shanghai/2018,可以在服务器端的路由中用正则表达式截取: 查询字符串(query string), ...
- HTTP请求报文(请求行、请求头、请求体)
HTTP协议 1.简介 HTTP协议(Hyper Text Transfer Protocol,超文本传输协议),是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的 ...
- iOS开发——网络篇——文件下载(NSMutableData、NSFileHandle、NSOutputStream)和上传、压缩和解压(三方框架ZipArchive),请求头和请求体格式,断点续传Range
一.小文件下载 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion ...
- HTTP请求行、请求头、请求体详解
HTTP 请求头各参数具体含义 Header 解释 示例Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/htmlAccept-Charset 浏览器可以接 ...
- HTTP请求行、请求头、请求体详解(转)
转自 https://blog.csdn.net/u010256388/article/details/68491509/ HTTP请求报文解剖 HTTP请求报文由3部分组成(请求行+请求头+ ...
- 【校招面试 之 网络】第3题 HTTP请求行、请求头、请求体详解
1.HTTP请求报文解剖 HTTP请求报文由3部分组成(请求行+请求头+请求体): 下面是一个实际的请求报文: ①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE.HEA ...
随机推荐
- Combination Sum I&&II(经典的回溯算法题)
I: Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C w ...
- 转:使用IDA动态调试WanaCrypt0r中的tasksche.exe
逆向分析——使用IDA动态调试WanaCrypt0r中的tasksche.exe 转:http://www.4hou.com/technology/4832.html 2017年5月19日发布 导语: ...
- Python3 文件操作基本语法
对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 f = open('lyrics') #打开文件 first_line = f.readline() prin ...
- python笔记二:常用数据类型操作
1.切片:常用于取list或tuple的部分元素的操作 1)l=[1,2,3,4,5,6] l[:3]表示取前3个值,l[1:5]表示1到5个值, L[-3:]从列表最后往前数即最后3个数.... 2 ...
- SystemProperties cannot be resolved错误
单独用eclipse打开一个工程,出现SystemProperties.get()会出现SystemProperties cannot be resolved.错误 1. 引用SystemProper ...
- JAX-WS文章汇总
学习路线图 传送门 最简单的Web Service实现- 这里提供一个最简单的Web Service的实现,基于JAX-WS.除了jdk不需要任何其他jar包,使用Eclipse提供的Web Serv ...
- 洛谷——P2381 圆圆舞蹈
P2381 圆圆舞蹈 题目描述 熊大妈的乃修在时针的带领下,围成了一个圆圈舞蹈,由于没有严格的教育,奶牛们之间的间隔不一致. 奶牛想知道两只最远的奶牛到底隔了多远.奶牛A到B的距离为A顺时针走和逆时针 ...
- cpu亲和性绑定
将进程与cpu绑定,最直观的好处就是减少cpu之间的cache同步和切换,提高了cpu cache的命中率,提高代码的效率.从cpu架构上,NUMA拥有独立的本地内存,节点之间可以通过互换模块做连接和 ...
- 【go】继续go go go,ubuntu环境搭建及golang的依赖关系分析
这次是在ubuntu14.04 amd64上搭建go的编译环境,使用的IDE换成了sublime text,具体步骤参照的是 http://blog.csdn.net/aqiang912/articl ...
- [ARC 066] Tutorial
Link: ARC 066 传送门 C: 如果存在可行方案则答案为$2^{n/2}$ #include <bits/stdc++.h> using namespace std; #defi ...