Nginx 基础配置(三):内置变量
在客户端的请求过程中,Nginx 提供了内置变量来获取 HTTP 和 TCP 的信息。
注意: Nginx 1.9 之后开始支持 TCP 代理,这使 Nginx 的功能更为丰富。
一、常见内置变量
常见内置变量如下:
$arg_name:URL 请求中的参数,即“?”后面的 key=value&key1=value1,这里有两个参数,名字分别为 key 和 key1。
$args:URL 中的所有请求的参数值。
$binary_remote_addr:客户端地址的二进制形式, 固定长度为4个字节,通常和限速模块一起使用。
$body_bytes_sent:传输给客户端的字节数,响应头不计算在内;这个变量和Apache的mod_log_config模块中的“%B”参数保持兼容
$bytes_sent:传输给客户端的总字节数 (1.3.8, 1.2.5)
$connection:TCP连接的序列号 (1.3.8, 1.2.5)
$connection_requests:TCP连接当前的请求数量 (1.3.8, 1.2.5)
$content_length:“Content-Length” 请求头字段
$content_type:“Content-Type” 请求头字段
$cookie_name:cookie名称
$document_root:当前请求的文档根目录或别名
$document_uri:设置 $uri 的别名,同 $uri
$geoip_city:城市名称,在 geoip 模块中使用。
$host:优先级如下:HTTP请求行的主机名>”HOST”请求头字段>符合请求的服务器名
$hostname:运行 Nginx 的服务器名
$http_refer:表示请求是从哪个页面链接过来的。
$http_user_agent:客户端浏览器的相关信息。
$http_name:匹配任意请求头字段; 变量名中的后半部分“name”可以替换成任意请求头字段,如在配置文件中需要获取http请求头:“Accept-Language”,那么将“-”替换为下划线,大写字母替换为小写,形如:$http_accept_language即可。
$https:如果开启了SSL安全模式,值为“on”,否则为空字符串。
$is_args:如果请求中有参数,值为“?”,否则为空字符串。
$limit_rate:用于设置响应的速度限制,详见 limit_rate。
$msec:当前的Unix时间戳 (1.3.9, 1.2.6),日志写入时间,单位为秒,精度是毫秒。
$nginx_version:nginx版本
$pid:工作进程的PID
$pipe:如果请求来自管道通信,值为“p”,否则为“.” (1.3.12, 1.2.7)
$proxy_protocol_addr:获取代理访问服务器的客户端地址,如果是直接访问,该值为空字符串。(1.5.12)
$query_string:同 $args
$realip_remote_addr:保留原来的客户地址,在 real_ip 模块中使用。
$realpath_root:当前请求的文档根目录或别名的真实路径,会将所有符号连接转换为真实路径。
$remote_addr:客户端IP地址
$remote_port:客户端端口
$remote_user:客户端用户名,通常在 Auth Basic 模块中使用,用于HTTP基础认证服务的用户名
$request:记录请求的的 URL 和 HTTP。
$request_body:客户端的请求主体
此变量可在location中使用,将请求主体通过proxy_pass, fastcgi_pass, uwsgi_pass, 和 scgi_pass传递给下一级的代理服务器。
$request_body_file:将客户端请求主体保存在临时文件中。文件处理结束后,此文件需删除。如果需要之一开启此功能,需要设置client_body_in_file_only。如果将次文件传递给后端的代理服务器,需要禁用request body,即设置proxy_pass_request_body off,fastcgi_pass_request_body off, uwsgi_pass_request_body off, or scgi_pass_request_body off 。
$request_completion:如果请求成功,值为”OK”,如果请求未完成或者请求不是一个范围请求的最后一部分,则为空。
$request_filename:当前请求的文件路径,基于 root 或 alias 指令和 URI 请求生成。
$request_length:请求的长度 (包括请求的地址, http请求头和请求主体) (1.3.12, 1.2.7)
$request_method:HTTP请求方法,通常为“GET”或“POST”
$request_time:处理客户端请求使用的时间 (1.3.9, 1.2.6); 从读取客户端的第一个字节开始计时。
$request_uri:当前客户端请求的原始URI,带参数,无法修改,请查看 $uri 更改或重写 URI ,不包含主机名,例如:”/cnphp/test.php?arg=freemouse”。
$scheme:使用的请求协议, “http” 或 “https”
$sent_http_name:可以设置任意http响应头字段; 变量名中的后半部分“name”可以替换成任意响应头字段,如需要设置响应头Content-length,那么将“-”替换为下划线,大写字母替换为小写,形如:$sent_http_content_length 4096即可。
$server_addr:服务器端 IP 地址,需要注意的是:为了避免访问linux系统内核,应将ip地址提前设置在配置文件中。
$server_name:服务器名,如:www.cnphp.info
$server_port:服务器端口
$server_protocol:请求采用的协议名称和版本号,即服务器的 HTTP 版本, 通常为 “HTTP/1.0” 或 “HTTP/1.1”
$status:HTTP响应代码 (1.3.2, 1.2.2),即状态码。
$tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space:客户端TCP连接的具体信息
$time_iso8601:服务器时间的ISO 8610格式 (1.3.12, 1.2.7)
$time_local:服务器时间(LOG Format 格式) (1.3.12, 1.2.7),在通用日志格式下的本地时间。
$upstream_addr:请求反向代理到后端服务器的 IP 地址
$upstream_port:请求反向代理到后端服务器的端口号
$upstream_response_time:请求在后端服务器消耗的时间
$upstream_status:请求在后端服务器的 HTTP 响应状态
$uri:请求中的当前URI(不带请求参数,参数位于$args),可以不同于浏览器传递的$request_uri的值,在请求过程中 URI 可能会被改变,如在内部重定向或者使用index指令指定索引文件时,$uri不包含主机名,如”/foo/bar.html”。
二、常见内置变量实战技巧
Nginx 的内置变量主要用于日志记录和分析,以及业务逻辑的处理。
1.$arg_name
示例:
location / {
if ($arg_at = '5') {
proxy_pass http://b;
}
proxy_pass http://a;
}
请求的默认路径是 http://a,如果 URL 中的参数是 at=5 ,则请求路径变为 http://b。
2.$body_bytes_sent 和 $bytes_sent
这两个变量的差值就是 HTTP 响应头的大小。如果两个值相差悬殊,那么响应头就很大,需要确保 proxy_buffer 设置了合适的大小,如果超过 proxy_buffer 的值,error.log就会显示如下内容:
upstream sent too big header while reading response header from upstream
可以通过修改下面的参数值来解决这个问题:
proxy_buffers 4 256k;
proxy_buffer_size 128k;
proxy_busy_buffers_size 256k;
3.$realip_remote_addr
在 Nginx 1.9.7 加入了 ngx_http_realip_module 的变量,此变量可以获取用户的IP地址(如常见的代理或 CDN 的节点IP地址);
4.$request_time 和 $upstream_response_time
$upstream_response_time 是在 Nginx 启用了 upstream 的情况下,从 Nginx 与后端建立连接开始到接收完数据然后关闭连接为止的时间。$request_time 指从接收到用户请求到发送完响应数据的时间,包括接收请求数据的时间、程序响应时间和输出响应数据的时间。
如果要检查后端服务的性能,需要使用 $upstream_response_time 的值。
5.$uri 和 $request_uri
$uri 记录的是执行一系列内部重定向操作后最终传递到后端服务器的 URL(不包含参数 $args 的值)
$request_uri 记录的是当前请求的原始 URL (包括参数),如果没有执行内部重定向操作,去掉参数后的值和 $uri 的值是一样的。在线上环境中排查问题时,如果在后端服务中看到的请求和在 Nginx 中存放的 $request_uri 无法匹配。可以考虑去 $uri 里面进行查找。
6.$scheme
如将 HTTP 请求重定向到 HTTPS,示例代码如下:
if ($scheme = 'http') {
rewrite ^/(.*)$ https://$host/$1 redirect;
}