GolangHub

公众号:Golang语言开发栈

nginx配置与优化

nginx配置与优化

Nginx的操作

Linux安装Nginx

Nginx安装方法,为了节省篇幅不再赘述,大家可以搜索相关教程或者参考我的一篇老文Lnmp环境搭建-安装Nginx

如何查看Nginx可选择的编译选项

1
2
3
4
5
6
7
8
9
10
11
12
13
cd nginx-1.13.12/
./configure --help

--help print this message

--prefix=PATH set installation prefix
--sbin-path=PATH set nginx binary pathname
--modules-path=PATH set modules path
--conf-path=PATH set nginx.conf pathname
--error-log-path=PATH set error log pathname
--pid-path=PATH set nginx.pid pathname
--lock-path=PATH set nginx.lock pathname
省略...
Nginx启动

假设Nginx安装在/user/local/nginx目录中,启动Nginx的命令是:

1
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

参数“-c”指定了配置文件的路径,如果不加“-c”参数,Nginx会默认加载其安装目录的conf子目录中的nginx.conf文件,在本例中即:/usr/local/nginx/conf/nginx.conf

Nginx停止

一般通过发送信号给Nginx主进程的方式来停止Nginx。

我们可以通过ps命令来查找Nginx的主进程号:

1
2
3
4
5
6
7
8
9
10
11
ps -ef | grep nginx
www 7931 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7932 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7933 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7934 29211 0 12:23 ? 00:00:00 nginx: worker process
www 7935 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7936 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7937 29211 0 12:23 ? 00:00:01 nginx: worker process
www 7938 29211 0 12:23 ? 00:00:01 nginx: worker process
frank 14641 13844 0 17:12 pts/5 00:00:00 grep nginx
root 29211 1 0 2017 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx

以上数据显示, 一个Nginx进程的备注信息为“master process”,表示它为主进程,另外8个Nginx进程的备注信息为“worker process”,表示它们为子进程,29211为主进程号。

如果nginx.conf配置文件中指定了pid文件的存放路径(例如:/usr/local/nginx/logs/nginx.pid),该文件中存放的就是Nginx当前的主进程号。如果没有指定pid文件的存放路径,nginx.pid文件默认存放在Nginx安装目录的logs目录下。所以,我们可以直接通过以下命令来完成平滑重启,省下了上面我们讲的寻找Nginx主进程号的步骤:

1
kill -信号类型 `cat /usr/local/nginx/logs/nginx.pid`

从容停止Nginx

kill -QUIT Nginx主进程号

1
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid`

快速停止Nginx

kill -TERM Nginx主进程号

1
kill -TERM `cat /usr/local/nginx/logs/nginx.pid`

kill -INT Nginx主进程号

1
kill -INT `cat /usr/local/nginx/logs/nginx.pid`

强制停止Nginx

pkill -9 nginx

Nginx平滑重启

修改了Nginx的配置文件,需要重启Nginx才能生效,重启Nginx同样可以使用发送信号给Nginx主进程的方式来进行。不过在重启Nginx之前,最好确认Nginx配置文件(nginx.conf)的语法是否正确,否则Nginx将不会加载修改后的新配置文件。

通过以下命令可以判断Nginx配置文件是否正确:

/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf

如果配置文件不正确,将会提示配置文件的第几行出错:

1
[emerg]: unknown directive "abc" in/usr/local/nginx/conf/nginx.conf:55 configuration file/usr/local/nginx/conf/nginx.conf test failed

如果配置文件正确,将提示以下两行信息:

1
the configuration file/usr/local/nginx/conf/nginx.conf syntax is ok configuration file/usr/local/nginx/conf/nginx.conf test is successful

配置文件正确,就可以平滑重启Nginx了。

kill -HUP Nginx主进程号

1
kill -HUP `cat /usr/local/nginx/logs/nginx.pid`

当Nginx接收到HUP信号时,它会尝试先解析配置文件(如果指定配置文件就使用指定的,否则就使用默认的),如果成功,就应用新的配置文件(例如,重新打开日志文件或监听的套接字)。之后,Nginx运行新的工作进程并从容关闭旧的工作进程。通知工作进程关闭监听套接字,但是继续为当前连接的客户提供服务。所有客户端的服务完成后,旧的工作进程被关闭。

如果新的配置文件应用失败,Nginx将继续使用旧的配置进行工作。

Nginx的信号控制

Nginx支持以下几种信号:

  • TERM,INT快速关闭
  • HUP平滑重启,重新加载配置文件
  • QUIT从容关闭
  • USR1重新打开日志文件,在切割日志时用途较大
  • USR2平滑升级可执行程序
  • WINCH从容关闭工作进程
Nginx的平滑升级

当需要将正在运行的Nginx升级、添加/删除服务器模块时,可以在不中断服务的情况下,使用新版本、重编译的Nginx可执行程序替换旧版本的可执行程序。步骤如下:

  1. 使用新的可执行程序替换旧的可执行程序,对于编译安装的Nginx,可以将新版本编译安装到旧版本的Nginx安装路径中。替换之前,最好备份一下旧的可执行文件。

  2. 发送以下指令:

    kill -USR2 旧版本的Nginx主进程号

  3. 旧版本的Nginx的主进程将重命名它的.pid文件为.oldbin(例如:/usr/local/nginx/logs/nginx.pid.oldbin),然后执行新版本的Nginx可执行程序,依次启动新的主进程和新的工作进程。

  4. 此时,新、旧版本的Nginx实例会同时运行,共同处理输入的请求。要逐步停止旧版本的Nginx实例,你必须发送WINCH信号给旧的主进程,然后,它的工作进程就将开始从容关闭:

    kill -WINCH 旧版本的Nginx主进程号

  5. 一段时间后,旧的工作进程(worker process)处理了所有已连接的请求后退出,仅由新的工作进程来处理输入的请求了。

  6. 这时候,我们可以决定使用新版本,还是恢复到旧版本:

    恢复旧版本:

    1
    2
    3
    kill -HUP 旧的主进程号 # Nginx将在不重载配置文件的情况下启动它的工作进程
    kill -QUIT 新的主进程号 # 从容关闭其它工作进程(worker process)
    kill -TERM 新的主进程号 # 强制退出

    kill新的主进程号或旧的主进程号:如果某些原因新的工作进程不能退出,则向其发送kill信号。

    新的主进程退出后,旧的主进程会移除.oldbin后缀,恢复为它的.pid文件,这样,一切就都恢复到升级之前了。

    使用新版本:

    如果尝试升级成功,而你也希望保留新的服务器时,可发送QUIT信号给旧的主进程,使其退出而只留下新的服务器运行。

Nginx的基本配置与优化

Nginx完整配置示例

Nginx的配置文件默认在Nginx程序安装目录的conf二级目录下,主配置文件为nginx.conf,假如你的Nginx安装在/usr/local/nginx目录下,那么默认的主配置文件则为/usr/local/nginx/conf/nginx.conf,下面是Nginx完整配置示例(不同版本Nginx的主配置文件有轻微差异):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 使用的用户和组
user www www;
# 指定工作进程数(一般等于CPU的总核数或总核数的两倍,例如两个四核CPU,则总核数为8)
worker_processes auto;
# 指定错误日志存放路径,错误日志记录级别可选项为:[ debug | info | notice | warn | error | crit ]
error_log /home/wwwlogs/nginx_error.log crit;
# 指定pid存放路径
pid /usr/local/nginx/logs/nginx.pid;
# 指定文件描述符数量
#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 51200;

events
{
# 使用的网络IO模型,Linux系统推荐采用epoll模型,FreeBSD系统推荐采用kqueue模型
use epoll;
# 允许的连接数
worker_connections 51200;
multi_accept on;
}

http
{
include mime.types;
default_type application/octet-stream;

server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
# 设置客户端能够上传的文件大小
client_max_body_size 50m;

sendfile on;
tcp_nopush on;

keepalive_timeout 60;

tcp_nodelay on;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
# 开启gzip压缩
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";

#limit_conn_zone $binary_remote_addr zone=perip:10m;
##If enable limit_conn_zone,add "limit_conn perip 10;" to server section.

server_tokens off;
access_log off;

server
{
listen 80 default_server;
#listen [::]:80 default_server ipv6only=on;
server_name _;
index index.html index.htm index.php;
root /home/wwwroot/default;

#error_page 404 /404.html;

# Deny access to PHP files in specific directory
#location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; }

include enable-php.conf;

location /nginx_status
{
stub_status on;
access_log off;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}

location ~ .*\.(js|css)?$
{
expires 12h;
}

location ~ /.well-known {
allow all;
}

location ~ /\.
{
deny all;
}

access_log /home/wwwlogs/access.log;
}
include vhost/*.conf;
}

通过上面的Nginx主配置文件可以看出,nginx.conf的配置文件结构主要由以下几部分构成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
events
{

}

http
{
server
{

}
server
{

}
}
Nginx的虚拟主机配置

虚拟主机简介

虚拟主机使用的是特殊的软硬件技术,它把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机,每台虚拟主机都可以是一个独立的网站,可以具有独立的域名,具有完整的Internet服务器功能(WWW、FTP、Email等),同一台主机上的虚拟主机之间是完全独立的。从网站访问者来看,每一台虚拟主机和一台独立的主机完全一样。

利用虚拟主机,不用为每个要运行的网站提供一台单独的Nginx服务器或单独运行一组Nginx进程。虚拟主机提供了在同一台服务器、同一组Nginx进程上运行多个网站的功能。

在Nginx配置文件(nginx.conf)中,一个最简化的虚拟主机配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
http
{
server
{
listen 80 default;
server_name _ *;
access_log logs/default.access.log combined;
location / {
index index.html
root /data/www/server1;
}
}
}

跟Apache一样,Nginx也可以配置多种类型的虚拟主机:一是基于IP的虚拟主机,二是基于域名的虚拟主机,三是基于端口的虚拟主机。

配置基于IP的虚拟主机

  1. 添加IP别名

    Linux、FreeBSD操作系统都允许添加IP别名。

    IP别名就是可以在一块物理网卡上绑定多个IP地址。这样就能够在使用单一网卡的同一个服务器上运行多个基于IP的虚拟主机。

    设置IP别名也非常容易,只需配置系统上的网络接口,让它监听额外的IP地址。

    在Linux系统上,可以使用标准的网络配置工具(比如ifconfig和route命令)添加IP别名。以下是天机IP别名的示例:

    • 先用ifconfig命令查看该服务器的IP地址。下面这台服务器有一块物理网卡设备eth0s3和本地回环设备lo,eth0s3的IP地址为10.58.95.138,本地回环lo的IP地址为127.0.0.1。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
      inet 10.58.95.138 netmask 255.255.252.0 broadcast 10.58.95.255
      inet6 fe80::d3a5:36fd:8134:ff44 prefixlen 64 scopeid 0x20<link>
      ether 08:00:27:3d:a2:77 txqueuelen 1000 (Ethernet)
      RX packets 5575 bytes 388687 (379.5 KiB)
      RX errors 0 dropped 0 overruns 0 frame 0
      TX packets 103 bytes 14226 (13.8 KiB)
      TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

      lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
      inet 127.0.0.1 netmask 255.0.0.0
      inet6 ::1 prefixlen 128 scopeid 0x10<host>
      loop txqueuelen 1 (Local Loopback)
      RX packets 68 bytes 5908 (5.7 KiB)
      RX errors 0 dropped 0 overruns 0 frame 0
      TX packets 68 bytes 5908 (5.7 KiB)
      TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

      本地回环代表设备的本地虚拟接口,所以默认被看作是永远不会宕掉的接口。它的主要作用有两个:

      一是测试本机的网络配置,能PING通127.0.0.1说明本机的网卡和IP协议安装都没有问题;

      另一个作用是某些SERVER/CLIENT的应用程序在运行时需调用服务器上的资源,一搬要指定SERVER的IP地址,但当该程序要在同一台机器上运行且没有别的SERVER时,就可以把SERVER的资源装在本机上,SERVER的IP地址设为127.0.0.1也同样可以运行。

    • 在eth0s3网卡设备上添加两个IP别名10.58.95.139和10.58.95.140,可以通过以下的ifconfig和route命令来进行:

      1
      2
      3
      4
      	[root@localhost ~]# /sbin/ifconfig enp0s3:1 10.58.95.139 broadcast 10.58.95.255 netmask 255.255.252.0 up
      [root@localhost ~]# /sbin/route add -host 10.58.95.139 dev enp0s3:1
      [root@localhost ~]# /sbin/ifconfig enp0s3:2 10.58.95.140 broadcast 10.58.95.255 netmask 255.255.252.0 up
      [root@localhost ~]# /sbin/route add -host 10.58.95.140 dev enp0s3:2

      再执行ifconfig命令,就可以看到eth0s3网卡设备上绑定了两个IP别名,如下所示:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      ifconfig
      enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
      inet 10.58.95.138 netmask 255.255.252.0 broadcast 10.58.95.255
      inet6 fe80::d3a5:36fd:8134:ff44 prefixlen 64 scopeid 0x20<link>
      ether 08:00:27:3d:a2:77 txqueuelen 1000 (Ethernet)
      RX packets 188849 bytes 172001311 (164.0 MiB)
      RX errors 0 dropped 0 overruns 0 frame 0
      TX packets 38062 bytes 2744800 (2.6 MiB)
      TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

      enp0s3:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
      inet 10.58.95.139 netmask 255.255.252.0 broadcast 10.58.95.255
      ether 08:00:27:3d:a2:77 txqueuelen 1000 (Ethernet)

      enp0s3:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
      inet 10.58.95.140 netmask 255.255.252.0 broadcast 10.58.95.255
      ether 08:00:27:3d:a2:77 txqueuelen 1000 (Ethernet)

      lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
      inet 127.0.0.1 netmask 255.0.0.0
      inet6 ::1 prefixlen 128 scopeid 0x10<host>
      loop txqueuelen 1 (Local Loopback)
      RX packets 68 bytes 5908 (5.7 KiB)
      RX errors 0 dropped 0 overruns 0 frame 0
      TX packets 68 bytes 5908 (5.7 KiB)
      TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

      从另外一台服务器ping 10.58.95.139 和 10.58.95.140两个IP,如果能够ping通,则证明配置无误。但是,通过ifconfig和route配置的IP别名在服务器重启后会消失,不过可以将这两条ifconfig和route命令添加到/etc/rc.local文件中,让系统开机时自动运行,以下是相关命令:
      vi /etc/rc.local

      在文件末尾增加以下内容,然后保存退出即可:

      1
      2
      3
      4
      /sbin/ifconfig enp0s3:1 10.58.95.139 broadcast 10.58.95.255 netmask 255.255.252.0 up
      /sbin/route add -host 10.58.95.139 dev enp0s3:1
      /sbin/ifconfig enp0s3:2 10.58.95.140 broadcast 10.58.95.255 netmask 255.255.252.0 up
      /sbin/route add -host 10.58.95.140 dev enp0s3:2
  2. 配置基于IP的虚拟主机

    下面开始配置基于IP的虚拟主机。无论是通过IP别名在一台服务器上配置多个IP地址,还是通过多块网卡在服务器上配置多个IP地址,在Nginx中都能将其配置成为基于IP的虚拟主机。

    接下来在Nginx配置文件(nginx.conf)中,分别对10.58.95.138、10.58.95.139、10.58.95.140三个IP配置三个纯净态HTML支持的虚拟主机,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    http
    {
    # 第一个虚拟主机
    server
    {
    # 监听IP和端口
    listen 10.58.95.138:80;
    # 主机名称
    server_name 10.58.95.138;
    # 访问日志文件存放路径
    access_log logs/server1.access.log combined;
    location /
    {
    # 默认首页文件,顺序从左向右,如果找不到index.html文件,则查找index.htm文件作为首页文件
    index index.html index.htm
    # HTML网页文件存放路径
    root /data/www/server1;
    }
    }
    # 第二个虚拟主机
    server
    {
    # 监听IP和端口
    listen 10.58.95.139:80;
    # 主机名称
    server_name 10.58.95.139;
    # 访问日志文件存放路径
    access_log logs/server2.access.log combined;
    location /
    {
    # 默认首页文件,顺序从左向右,如果找不到index.html文件,则查找index.htm文件作为首页文件
    index index.html index.htm
    # HTML网页文件存放路径
    root /data/www/server2;
    }
    }
    # 第三个虚拟主机
    server
    {
    # 监听IP和端口
    listen 10.58.95.140:80;
    # 主机名称
    server_name 10.58.95.140;
    # 访问日志文件存放路径
    access_log logs/server3.access.log combined;
    location /
    {
    # 默认首页文件,顺序从左向右,如果找不到index.html文件,则查找index.htm文件作为首页文件
    index index.html index.htm
    # HTML网页文件存放路径
    root /data/www/server3;
    }
    }
    }

    从上面配置文件可以看出,一段server{}就是一个虚拟主机,如果要配置多个虚拟主机,建立多段server{}配置即可,非常方便。监听的IP和端口也可以不写IP地址,只写端口,把它配置成listen 80;,则表示监听该服务器上所有的IP的80端口,可通过server_name区分不同的虚拟主机。

配置基于域名的虚拟主机

基于域名的虚拟主机是最常见的一种虚拟主机。只需要配置你的DNS服务器,将每个主机名映射到正确的IP地址,然后配置Nginx服务器,令其识别不同的主机名就可以了。这种虚拟主机技术,使很多虚拟主机可以共享一个IP地址,有效解决了IP地址不足的问题。所以,如果没有特殊要求使你必须用一个基于IP的虚拟主机,最好还是使用基于域名的虚拟主机。

配置基于域名的虚拟主机

我们将配置三个虚拟主机,第一个虚拟主机表示所有对域名aaa.domain.com的访问都由它来处理,第二个虚拟主机表示所有对域名bbb.otherdomain.com的访问都由它来处理,第三个虚拟主机表示对域名www.domain.com、domain.com,以及除了aaa.domain.com之外的所有*.domain.com二级域名的访问都由它来处理。每个虚拟主机的网页文件分别放在了不同的目录中,每个虚拟主机使用了不同的日志文件来记录访问日志,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
http
{
# 第一个虚拟主机
server
{
# 监听的端口
listen 80;
# 主机名称
server_name aaa.domain.com;
# 访问日志文件存放路径
access_log logs/aaa.domain.com.access.log combined;
location /
{
# 默认首页文件,顺序从左到右,如果找不到index.html文件,则查找index,htm文件作为首页文件
index index.html index.htm;
# HTML网页文件存放的目录
root /data/www/aaa.domain.com;
}
}
# 第二个虚拟主机
server
{
# 监听的端口
listen 80;
# 主机名称
server_name bbb.otherdomain.com;
# 访问日志文件存放路径
access_log logs/bbb.otherdomain.com.access.log combined;
location /
{
# 默认首页文件,顺序从左到右,如果找不到index.html文件,则查找index,htm文件作为首页文件
index index.html index.htm;
# HTML网页文件存放的目录
root /data/www/bbb.otherdomain.com;
}
}
# 第三个虚拟主机
server
{
# 监听的端口
listen 80;
# 主机名称
server_name www.domain.com domain.com *.domain.com;
# 访问日志文件存放路径
access_log logs/www.domain.com.access.log combined;
location /
{
# 默认首页文件,顺序从左到右,如果找不到index.html文件,则查找index,htm文件作为首页文件
index index.html index.htm;
# HTML网页文件存放的目录
root /data/www/www.domain.com;
}
}
}
Nginx的日志文件配置与切割

与Nginx日志相关的指令主要有两条,一条是log_format,用来设置日志的格式,另外一条是access_log,用来指定日志文件存放的路径、格式和缓存大小。两条指令在Nginx配置文件中的位置可以在http{}之间,也可以在虚拟主机之间,即server{}两个大括号之间。

  1. 用log_format指令设置日志格式

    • 语法:log_format name format [format...]

      name:定义格式的名称

      format:定义格式的样式

      log_format有一个默认的、无需设置的combined日志格式设置,相当于Apcahe的combined日志格式,其具体参数如下:

      1
      2
      3
      log_format combined '$remote_addr - $remote_user [$time_local] '
      '"$request" $status $body_bytes_sent '
      '"$http_referer" "$http_user_agent" ';

      我们也可以自定义日志的记录格式,但是log_format指令设置的name名称在Nginx配置文件中不能重复。

    • 获取客户端的真实IP地址

      假设将Nginx服务器作为Web服务器,位置负载均衡设备、Squid、Nginx反向代理之后,就不能获取到客户端的真实IP地址了。原因是经过反向代理后,由于在客户端和Web服务器之间增加了中间层,因此Web服务器无法直接拿到客户端的IP,通过$remote_addr变量拿到的将是反向代理服务器的IP地址。但是,反向代理服务器在转发请求的HTTP头信息中,可以增加X-Forwarded-For信息,用以记录原有的客户端IP地址和原来客户端请求的服务器地址。

      这时候,就要用log_format指令来设置日志格式,让日志记录X-Forwarded-For信息中的IP地址,即客户端的真实IP。

      示例:创建一个名为mylogformat的日志格式,再用$http_x_forwarded_for变量记录用户的X-Forwarded-For IP地址。

      1
      2
      3
      log_format mylogformat '$http_x_forwarded_for - $remote_user [$time_local] '
      '"$request" $status $body_bytes_sent '
      '"$http_referer" "$http_user_agent"';

      在日志格式中,$remote_addr$http_x_forwarded_for用于记录IP地址;

      $remote_user用于记录远程客户端用户名称;

      $time_local用于记录访问时间与时区;

      $request用于记录请求URL与HTTP协议;

      $status用于记录请求状态,例如成功的状态为200,页面未找到的状态为404;

      $body_bytes_send用于记录发送给客户端的文件主体内容大小;

      $http_referer用于记录是从哪个页面链接访问过来的;

      $http_user_agent用于记录客户端浏览器的相关信息。

  2. 用access_log指令指定日志文件存放路径

    • 语法 access_log path [format [buffer=size | off]]

      path:日志文件存放的路径

      format:使用log_format指令设置的日志格式的名称

      buffer=size 设置内存缓冲区大小,例如可以设置buffer=32k

    • 使用方法

      1. 关闭日志记录

        access_log off;

      2. 使用默认的combined格式的日志记录

        access_log /data/logs/filename.log;

        access_log /data/logs/filename.log combined;

      3. 使用自定义格式的日志记录,可以使用以下示例,其中的mylogformat是日志格式名称

        1
        2
        3
        4
        log_format mylogformat '$remote_addr = $remote_user [$time_local] "$request" '
        '$status $body_bytes_send "$http_referer" '
        '"$http_user_agent" $http_x_forwarded_for';
        access_log /data/logs/access.log mylogformat buffer=32k;
      4. 在Nginx0.7.4之后的版本中,access_log指令中的日志文件路径可以包含变量,例如:

        access_log /data/logs/$server_name.log combined;

        假设server_name指令设置的虚拟主机名称为test.domain.com,那么access_log指令将把访问日志记录在/data/logs/test.domain.com.log文件中。

        如果日志文件路径中含有变量,将存在以下一些限制:

        • Nginx进程设置的用户和组必须有对该路径创建文件的权限。假设Nginx的user指令设置的用户和用户组都是www,而/data/logs/目录的用户名和用户组为root,日志文件/data/logs/test.domain.com.log将无法被Nginx创建。

        • 缓冲将不会被调用。

        • 对于每一条日志记录,日志文件都将先打开文件,再写入日志记录,然后马上关闭。为了提高包含变量的日志文件存放路径的性能,需要使用open_log_file_cache指令设置经常被使用的日志文件描述符缓存。

          open_log_file_cache指令主要用来设置含有变量的日志路径的文件描述符缓存,语法如下:
          open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time] | off;

          该指令默认是禁止的,等同于:

          open_log_file_cache off;

          参数:

          max:设置缓存中最大文件描述符数量。如果超过设置的最大文件描述符数量,则采用LRU算法清除“较不常使用的文件描述符”。LRU算法的基本概念是:当内存缓冲区剩余的可用空间不够时,缓冲区尽可能地先保留使用在常使用的数据,将最近未使用的数据移除内存,腾出空间来加载另外的数据。

          inactive:设置一个时间,如果在设置的时间内没有使用此文件描述符,则自动删除此文件描述符。此参数为可选参数,默认的时间为10秒钟。

          min_uses:在参数inactive指定的时间范围内,如果日志文件超过被使用的次数,则将该日志文件的描述符记入缓存。默认次数为1.

          valid:设置多长时间检查一次,看一看变量指定的日志文件路径与文件名是否仍然存在。默认时间为60秒。

          off:禁止使用缓存。

示例:

`open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;`
  1. Nginx日志文件的切割

    生产环境中的服务器,由于访问日志文件增长速度非常快,日志太大会严重影响服务器效率。同时,为了方便对日志进行分析计算,需要对日志文件进行定时切割。定时切割的方式有按月切割、按日切割、按小时切割等。最常用的是按日切割。

    Nginx切割日志文件:

    1
    2
    mv /data/logs/access.log /data/logs/20180523.log
    kill -USR1 Nginx主进程号

    首先通过mv命令将日志文件重命名为/data/logs/20180523.log,然后发送kill -USR1信号给Nginx的主进程号,让Nginx重新生成一个新的日志文件/data/logs/access.log。如果nginx.conf配置文件中使用了pic /usr/local/nginx/logs/nginx.pid;指令,指定了pid文件的存放路径,我们可以通过cat这个pid文件活的Nginx的主进程号,命令如下:

    1
    kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

    如果想每天定时切割日志,还需要借助crontab。我们可以写一个按日切割日志,按年、月目录存放日志的shell脚本。

    vim /usr/local/nginx/sbin/cut_nginx_log.sh

    输入以下内容并保存:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!bin/bash
    # 这个脚本需要每天00:00运行

    # Nginx日志文件存放路径
    logs_path="/data/logs/"

    mkdir -p ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/
    mv ${logs_path}access.log ${logs_path}$(date -d "yesterday" + "%Y")/$(date -d "yesterday" +"%m")/access_$(date -d "yesterday" +"%Y%m%d").log
    kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

    另外,配置crontab每天凌晨00:00定时执行这个脚本:

    crontab -e

    输入以下内容并保存:

    1
    00 00 * * * /bin/bash /usr/local/nginx/sbin/cut_nginx_log.sh

    这个shell脚本和crontab配置主要实现的功能是:假设今天的日期为2018年5月23日,Nginx当前的日志文件为/data/logs/access.log,2018年5月24日00:00会执行cut_nginx_log.sh脚本,脚本首先创建一个目录/data/logs/2018/05/,然后将/data/logs/access.log文件移动并重命名为data/logs/2018/05/access_20180523.log,再发送kill -USR1信号给Nginx主进程号,告诉Nginx重新生成一个/data/logs/access.log文件,2018年5月24日的日志记录在这个新生成的日志文件中。而/data/logs/2018/05/access_20180523.log文件,就是2018年5月23日的日志文件。

更多精彩内容,请关注公众号 Golang语言开发栈公众号二维码
感谢赞赏.

Welcome to my other publishing channels