【架构】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 ...
随机推荐
- 禁止网页右键和复制,ctrl+a都不行。取消页面默认事件【全】。
document.oncontextmenu=new Function("event.returnValue=false");document.onselectstart=new ...
- bzoj 1449 费用流
思路:先把没有进行的场次规定双方都为负,对于x胜y负 变为x + 1胜 y - 1 负所需要的代价为 2 * C[ i ] * x - 2 * D[ i ] * y + C[ i ] + D[ i ...
- hdu多校 2
... 后面四个小时都在挂机很难受. 1010 裸的逆序对 //#pragma comment(linker, "/stack:200000000") //#pragma GCC ...
- 微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证
前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已 ...
- 使用jsonp形式跨域访问实现电商平台的左侧导航栏
电商平台有个具备的左侧商品类目的导航栏的结构. 通过jsonp跨域访问电商平台的后台管理系统商品分类.(主要实现后台Java代码) 实现基本步骤: 1.在后台管理系统中准备相应的json数据. poj ...
- django-BBS(2)
昨天设计了数据库和数据表,今天来进行页面前端的设计, 1.首先去bootstarp上,下载相应的模板和配置文件,添加到对应的位置 2.在templates中添加许多许多的html页面 如下 并 ...
- 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
- 洛谷——P3908 异或之和
P3908 异或之和 题目描述 求1 \bigoplus 2 \bigoplus\cdots\bigoplus N1⨁2⨁⋯⨁N 的值. A \bigoplus BA⨁B 即AA , BB 按位异或. ...
- 【webssh】shellinabox搭建
shellinabox搭建 centos环境安装命令 # yum install epel-release # yum install shellinabox 启动与关闭: service shell ...
- leetcode7 Rerver Integer
题意:数字反转 思路:醉了,提交了好几次,难点不在于怎么反转,而是判断是否益处,原题中给的是int,4个字节,32位,开始不知道怎么判断.现在知道了是limits.h中的INT_MIN和INT_MAX ...