Skip to content

Latest commit

 

History

History
276 lines (192 loc) · 10.9 KB

07、日志.md

File metadata and controls

276 lines (192 loc) · 10.9 KB

程序员技术交流、面试、职场、生活、游戏,综合讨论QQ群:387017550,群内经常发红包,欢迎加入

07、日志

1、默认配置和说明

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"';

#    access_log  logs/access.log  main;

说明:

  • $log_format 表示日志格式,main 表示该格式名;
  • $access_log 表示日志存放位置,main 表示采用格式名为 mian 的日志格式;
  • $remote_addr:远程客户端用户的 IP;
  • $remote_user:远程客户端用户名称;
  • $time_local:时间和时区;
  • $resuest:请求方式(比如GET)、请求URL(比如/)、HTTP协议(比如HTTP/1.1);
  • $status:HTTP状态码,例如成功是200,未找到是404;
  • $body_bytes_send:发送给客户端的主体文件内容大小,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容;
  • $http_referer:从哪个链接访问过来的(但非重定向可能为空);
  • $http_x_forwarded_for:重定向之前,用户真实的 IP 地址;

2、一些属性说明

log_format 属性:

只能放在 http 属性内(即和 server 平级的位置);

默认的格式名为 combined

access_log 属性:

可以放在多个位置,包括:

  • http
  • server
  • location
  • if in location
  • limit_except

log_format常用的变量参数

以下是我从其他地方拷贝过来的(出处较多,故不附链接),仅供参考;

参数                      说明                                         示例
$remote_addr             客户端地址                                    211.28.65.253
$remote_user             客户端用户名称                                --
$time_local              访问时间和时区                                18/Jul/2012:17:00:01 +0800
$request                 请求的URI和HTTP协议                           "GET /article-10000.html HTTP/1.1"
$http_host               请求地址,即浏览器中你输入的地址(IP或域名)     www.wang.com 192.168.100.100
$status                  HTTP请求状态                                  200
$upstream_status         upstream状态                                  200
$body_bytes_sent         发送给客户端文件内容大小,不包括响应头的大小         1547
$http_referer            url跳转来源                                   https://www.baidu.com/
$http_user_agent         用户终端浏览器等信息                           "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C;
$ssl_protocol            SSL协议版本                                   TLSv1
$ssl_cipher              交换数据中的算法                               RC4-SHA
$upstream_addr           后台upstream的地址,即真正提供服务的主机地址     10.10.10.100:80
$request_time            整个请求的总时间                               0.205
$upstream_response_time  请求过程中,upstream响应时间                    0.002

补充内容:
$bytes_sent             发送给客户端的总字节数。
$connection             连接的序列号。
$connection_requests    当前通过一个连接获得的请求数量。
$msec                   日志写入时间。单位为秒,精度是毫秒。
$pipe                  如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。
$request_length         请求的长度(包括请求行,请求头和请求正文)。
$time_iso8601           ISO8601标准格式下的本地时间。

3、改动实战

我们可以根据自己实际需要改为:

log_format mylogformat '$remote_addr | $http_x_forwarded_for | "$http_referer" | '
                    '$remote_user | $time_local | $http_host | "$request" | '
                    '$status | $body_bytes_sent | "$http_user_agent"';
access_log  logs/access2.log  mylogformat;

以上配置表示:

  • 日志存储到 logs/access2.log
  • 日志格式名是 mylogformat
  • 该格式是(注意,实际上不换行):
  • [重定向之前的用户 IP] | [原始用户访问 IP] | [用户访问的URL] |
  • [用户名] | [访问时间和时区] | [请求的域名的host部分] | [请求方式、地址、HTTP协议版本] |
  • [HTTP状态码] | [返回报文大小] | [用户浏览器信息]

示例数据:

- | "-" |  - | 24/Jan/2019:19:55:40 +0800 | a.test.com | "GET /index.html HTTP/1.1" | 200 | 396 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"

$remote_addr 和 $http_x_forwarded_for 的区别

  • $remote_addr 是用户 IP;
  • 但若如果被负载均衡设备、或者 Nginx 反向代理后,$remote_addr 则是反向代理设备的 IP;
  • 此时真实 IP 可能被添加到 HTTP 头信息中,属性名是 X-Forwarded-For ,$http_x_forwarded_for 可以获取到这个值;

4、关闭日志

非常简单

access_log off;

5、自定义日志格式名

Nginx 0.7.4 后,日志文件路径可以包含变量。

具体来说,可以包含server名,以及年月日时分秒等变量时间。

具体不多讲,参考以下代码和效果说明即可知道。

年月日时分秒:

if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})")
{
    set $year $1;
    set $month $2;
    set $day $3;
    set $hour $4;
    set $minutes $5;
    set $seconds $6;
}
  • 放在 server 范围内方可使用;
  • $time_iso8601 格式如下:2019-01-25T00:12:02+08:00
  • 因此 $year 为 2019,其他依次类推,很好理解;

$server_name :

之所以说 $server_name ,是因为我们通常日志是跟 $server_name 关联的。

配置方法:

server {
    listen       80;
    server_name  a.test.com;

    if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})")
    {
        set $year $1;
        set $month $2;
        set $day $3;
        set $hour $4;
        set $minutes $5;
        set $seconds $6;
    }

    # 核心在这里
    access_log  logs/[$year-$month-$day]$server_name.log  mylogformat;

    location / {
        root   html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

日志文件名:

写文章这天是2019-01-25

[2019-01-25]a.test.com.log

6、多日志配置

假如我在 http 有一次 access_log 配置,再在 server 有一次 access_log 配置。

那么优先匹配 server 的 access_log 的配置,取不到再取 http 的配置;

7、日志的读写说明

默认情况下:

  1. 运行 Nginx 的用户需要有读写权限,否则无法创建和读写;
  2. 无缓冲,即每产生一条日志,会先打开日志,写入,再关闭(IO较多);

由于IO较多,因此需要配置 open_log_file_cache 属性来避免 IO 带来的性能损失。

具体来说:

  1. 首先不能批量写入,原因在于,server可能有多个,而日志(access_log)的配置,是可以配置到 server 级的;
  2. 这会导致可能出现,两个 server 原本应该交叉写入的日志,实际却先写了第一个 server 的全部日志,再写了第二个 server 的全部日志;
  3. 但多次 IO 还是有一定性能损失;

于是分析linux对文件系统的管理,引一段别人写的博客:

    文件指针(fp)和文件描述符(fd)有什么关系呢?
    
    文件指针是指向一个FILE的结构体,这个结构体里包括一个文件描述符(在Windows下也被称为文件句柄)和一个I/O缓冲区。
    
    文件描述符用于C标准的IO库调用中,用于标识文件。
    
    FILE中包含文件描述符元素,可以用fopen()直接获取指针fp,然后使用fp获得fp中所包含文件描述符fd的信息。
    
    文件描述符应该是唯一的,而文件指针却不是唯一的,但指向的对象是唯一的。
    
    文件指针比fd更适合跨平台。
    
    文件描述符就是open文件时产生的一个很小的正整数,,是一个索引值。
    
    文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。
    
    每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。
    
    简单归纳:文件描述符(fd)只是一个整数,在open时产生,起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针file。 

我总结一下,简单来说,文件指针(fp) = 文件描述符(fd) + 其他的;

而 文件描述符(fd) 指向文件;

因此缓存 文件描述符(fd),可以加快 查找/打开 日志文件的速度;

在日志文件比较多的时候,缓存 文件描述符(fd) 可以提高性能。

因此有了 open_log_file_cache 配置属性。

open_log_file_cache 说明:

  1. 默认值为 off(关闭);
  2. 语法:open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];

属性说明:

  • max:(必填)设置缓存中最多容纳的文件描述符数量,如果被占满,采用LRU算法将描述符关闭。
  • inactive:(选填)设置缓存存活时间,默认是10s。
  • min_uses:(选填)在inactive时间段内,日志文件最少使用几次,该日志文件描述符记入缓存,默认是1次。
  • valid:(选填)设置多久对日志文件名进行检查,看是否发生变化,默认是60s。
  • off:不使用缓存,默认值为off。

基本用法:

open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

它可以配置在http、server、location作用域中。

例子中,设置缓存最多缓存1000个日志文件描述符,20s内如果缓存中的日志文件描述符至少被被访问2次,才不会被缓存关闭。每隔1分钟检查缓存中的文件描述符的文件名是否还存在。

主要应用于多个日志(使用了日志变量)时的场景。

8、参考链接