Nginx配置的核心功能说明 : Core functionality

Nginx运行命令

显示帮助信息

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

[root@RockyLinux9 ~]# nginx -h
nginx version: nginx/1.26.0
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
[-e filename] [-c filename] [-g directives]

选项:
-?,-h : 显示帮助信息
-v : 显示版本信息
-V : 显示版本信息和编译配置项
-t : 检查测试配置文件
-T : 检查测试配置文件并输出内容
-q : 在配置文件测试期间禁止显示非错误消息
-s signal : 向主进程发送信号: stop, quit, reopen, reload
-p prefix : 设置配置路径,默认: /usr/local/nginx/
-e filename : 设置错误日志文件,默认: logs/error.log
-c filename : 设置配置文件,默认: conf/nginx.conf
-g directives : 启动时指定全局配置项,而不修改配置文件,格式:k v;

显示版本信息

1
2
[root@RockyLinux9 ~]# nginx -v
nginx version: nginx/1.26.0

显示版本信息和编译配置项

1
2
3
4
5
6
7
[root@RockyLinux9 ~]# nginx -V
nginx version: nginx/1.26.0
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module

检查测试配置文件

1
2
3
[root@RockyLinux9 ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

检查测试配置文件并输出内容

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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
[root@RockyLinux9 ~]# nginx -T
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
# configuration file /usr/local/nginx/conf/nginx.conf:

#user nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;
pid run/nginx.pid;


events {
worker_connections 1024;
}


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

#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;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

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

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

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


# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

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

}

# configuration file /usr/local/nginx/conf/mime.types:

types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;

text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;

image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;

font/woff woff;
font/woff2 woff2;

application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;

application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;

audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;

video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}

在配置文件测试期间禁止显示非错误消息

1
2
3
[root@RockyLinux9 ~]# nginx -q
[root@RockyLinux9 ~]# echo $?
0

启动时指定全局配置项

  • (需为配置文件中未设置项),格式:k v;

    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
    # 原配置显示进程
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4680 1 0 21:49 ? 00:00:00 nginx: master process nginx
    nginx 4681 4680 0 21:49 ? 00:00:00 nginx: worker process

    # 停止服务
    [root@RockyLinux9 ~]# nginx -s stop

    # 注释如下两行
    [root@RockyLinux9 ~]# vim /usr/local/nginx/conf/nginx.conf
    #worker_processes 1;
    #pid run/nginx.pid;

    # 新pid文件不存在
    [root@RockyLinux9 ~]# ll /var/run/nginx.pid
    ls: cannot access '/var/run/nginx.pid': No such file or directory

    # 执行pid文件,指定进程数
    [root@RockyLinux9 ~]# nginx -g "pid /var/run/nginx.pid; worker_processes 2;"
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4698 1 0 21:58 ? 00:00:00 nginx: master process nginx -g pid /var/run/nginx.pid; worker_processes 2;
    nginx 4699 4698 0 21:58 ? 00:00:00 nginx: worker process
    nginx 4700 4698 0 21:58 ? 00:00:00 nginx: worker process
    [root@RockyLinux9 ~]# ll /var/run/nginx.pid
    -rw-r--r--. 1 root root 5 May 10 21:58 /var/run/nginx.pid

Nginx信号

向主进程发送信号

  • nginx -s stop:快速关闭。

  • kill -INT/TERM 主进程PID

    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
    #启动程序
    [root@RockyLinux9 ~]# nginx
    #查看进程
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4733 1 0 22:12 ? 00:00:00 nginx: master process nginx
    nginx 4734 4733 0 22:12 ? 00:00:00 nginx: worker process
    nginx 4735 4733 0 22:12 ? 00:00:00 nginx: worker process
    root 4737 4591 0 22:12 pts/0 00:00:00 grep --color=auto nginx
    # 快速关闭程序,无论进程是否有连接,都会直接断开
    [root@RockyLinux9 ~]# nginx -s stop
    # 确认
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4740 4591 0 22:12 pts/0 00:00:00 grep --color=auto nginx

    [root@RockyLinux9 ~]# nginx
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1517 1 0 23:47 ? 00:00:00 nginx: master process nginx
    nginx 1518 1517 0 23:47 ? 00:00:00 nginx: worker process
    nginx 1519 1517 0 23:47 ? 00:00:00 nginx: worker process
    root 1530 1408 0 23:52 pts/0 00:00:00 grep --color=auto nginx
    [root@RockyLinux9 ~]# kill -INT 1517
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1535 1408 0 23:52 pts/0 00:00:00 grep --color=auto nginx

    [root@RockyLinux9 ~]# nginx
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1537 1 0 May10 ? 00:00:00 nginx: master process nginx
    nginx 1538 1537 0 May10 ? 00:00:00 nginx: worker process
    nginx 1539 1537 0 May10 ? 00:00:00 nginx: worker process
    root 1568 1408 0 00:05 pts/0 00:00:00 grep --color=auto nginx
    [root@RockyLinux9 ~]# kill -TERM 1537
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1570 1408 0 00:05 pts/0 00:00:00 grep --color=auto nginx

优雅的关闭

  • nginx -s quit:优雅的关闭。

  • kill -QUIT 主进程PID

    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
    # 创建一个1G的测试文件
    [root@RockyLinux9 ~]# dd if=/dev/zero of=/usr/local/nginx/html/Linuxjsz bs=1M count=1024
    1024+0 records in
    1024+0 records out
    1073741824 bytes (1.1 GB, 1.0 GiB) copied, 3.11659 s, 345 MB/s

    # 通过客户端访问的方式进行文件下载
    [root@RockyLinux9 ~]# wget http://192.168.199.152/Linuxjsz
    Connecting to 192.168.199.152:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 1073741824 (1.0G) [application/octet-stream]
    Saving to: ‘Linuxjsz’

    Linuxjsz 100%[=====================>] 1.00G 147MB/s in 7.4s

    22:41:54 (139 MB/s) - ‘Linuxjsz’ saved [1073741824/1073741824]
    # 查看进程情况,正常运行中
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4824 1 0 22:41 ? 00:00:00 nginx: master process nginx
    nginx 4825 4824 0 22:41 ? 00:00:00 nginx: worker process
    nginx 4826 4824 0 22:41 ? 00:00:00 nginx: worker process
    root 4828 4591 0 22:41 pts/0 00:00:00 grep --color=auto nginx

    # 下载过程中发送quit信号
    [root@RockyLinux9 ~]# nginx -s quit

    # 查看进程情况,此时其中一个worker进程已关闭,而存在进程处于即将关闭状态
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4824 1 0 22:41 ? 00:00:00 nginx: master process nginx
    nginx 4825 4824 3 22:41 ? 00:00:00 nginx: worker process is shutting down
    root 4831 4591 0 22:41 pts/0 00:00:00 grep --color=auto nginx

    # 查看进程情况,此时nginx程序已关闭
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4833 4591 0 22:42 pts/0 00:00:00 grep --color=auto nginx

    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1641 1 0 00:12 ? 00:00:00 nginx: master process nginx
    nginx 1642 1641 0 00:12 ? 00:00:00 nginx: worker process
    nginx 1643 1641 0 00:12 ? 00:00:00 nginx: worker process
    root 1645 1408 0 00:12 pts/0 00:00:00 grep --color=auto nginx
    [root@RockyLinux9 ~]# kill -QUIT 1641
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1641 1 0 00:12 ? 00:00:00 nginx: master process nginx
    nginx 1643 1641 0 00:12 ? 00:00:00 nginx: worker process is shutting down
    root 1756 1408 0 00:13 pts/0 00:00:00 grep --color=auto nginx

启动新的工作进程

  • nginx -s reload:重新加载配置文件,启动新的工作进程,优雅的关闭旧进程。

  • kill -HUP 主进程PID

    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
    # 查看进程情况
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4751 1 0 22:22 ? 00:00:00 nginx: master process nginx
    nginx 4752 4751 0 22:22 ? 00:00:00 nginx: worker process
    nginx 4753 4751 0 22:22 ? 00:00:00 nginx: worker process
    root 4810 4591 0 22:30 pts/0 00:00:00 grep --color=auto nginx
    # 发送reload信号
    [root@RockyLinux9 ~]# nginx -s reload
    # 查看进程情况,发现主进程未发生变化,而两个worker进程的pid更改了,启动时间也发生了变化
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 4751 1 0 22:22 ? 00:00:00 nginx: master process nginx
    nginx 4812 4751 0 22:30 ? 00:00:00 nginx: worker process
    nginx 4813 4751 0 22:30 ? 00:00:00 nginx: worker process
    root 4815 4591 0 22:30 pts/0 00:00:00 grep --color=auto nginx

    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1761 1 0 00:16 ? 00:00:00 nginx: master process nginx
    nginx 1762 1761 0 00:16 ? 00:00:00 nginx: worker process
    nginx 1763 1761 0 00:16 ? 00:00:00 nginx: worker process
    root 1765 1408 0 00:16 pts/0 00:00:00 grep --color=auto nginx
    [root@RockyLinux9 ~]# kill -HUP 1761
    [root@RockyLinux9 ~]# ps -ef|grep nginx
    root 1761 1 0 00:16 ? 00:00:00 nginx: master process nginx
    nginx 1766 1761 0 00:17 ? 00:00:00 nginx: worker process
    nginx 1767 1761 0 00:17 ? 00:00:00 nginx: worker process
    root 1769 1408 0 00:17 pts/0 00:00:00 grep --color=auto nginx

重新生成日志文件

  • nginx -s reopen:重新生成日志文件。可用于定期备份日志文件

  • kill -USR1 主进程PID

    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
    # 查看日志文件
    [root@RockyLinux9 ~]# ll -h /usr/local/nginx/logs/
    total 12K
    -rw-r--r--. 1 root root 4.0K May 10 22:23 access.log
    -rw-r--r--. 1 root root 1.8K May 10 22:22 error.log
    -rw-r--r--. 1 root root 5 May 10 22:22 nginx.pid

    # 修改日志名称
    [root@RockyLinux9 ~]# mv /usr/local/nginx/logs/access.log{,.bak}
    [root@RockyLinux9 ~]# ll -h /usr/local/nginx/logs/
    total 12K
    -rw-r--r--. 1 root root 4.0K May 10 22:23 access.log.bak

    # 通过浏览器访问页面,显示访问日志还是写入到了原文件中
    [root@RockyLinux9 ~]# ll -h /usr/local/nginx/logs/
    total 16K
    -rw-r--r--. 1 root root 4.4K May 10 22:27 access.log.bak

    # 发送reopen信号,新创建了一个日志文件,再访问页面,日志则被写入到了新文件中
    [root@RockyLinux9 ~]# nginx -s reopen
    [root@RockyLinux9 ~]# ll -h /usr/local/nginx/logs/
    total 16K
    -rw-r--r--. 1 nginx root 0 May 10 22:28 access.log
    -rw-r--r--. 1 root root 4.4K May 10 22:27 access.log.bak
    [root@RockyLinux9 ~]# ll -h /usr/local/nginx/logs/
    total 20K
    -rw-r--r--. 1 nginx root 466 May 10 22:28 access.log
    -rw-r--r--. 1 root root 4.4K May 10 22:27 access.log.bak

Nginx启动

  • 启动nginx 格式:nginx安装目录地址 -c nginx配置文件地址

    1
    2
    3
    /usr/local/nginx/sbin/nginx -t  -c  /etc/nginx/nginx.conf
    # - 在启动命令-c 前加 -t 验证nginx配置文件是否正确
    /usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf
  • 重启Nginx服务

    1
    2
    # 方法一:进入nginx可执行目录sbin下,输入命令`./nginx -s reload` 即可
    nginx -s reload;tail -f /usr/local/nginx/logs/access.log
  • 重启Nginx服务(方法二):

    1
    2
    3
    4
    5
    # 查找当前nginx进程号
    ps -ef |grep nginx
    cat /var/run/nginx.pid
    # kill -HUP 进程号
    kill -HUP 1540
  • 停止Nginx服务

    1
    2
    3
    4
    5
    6
    7
    8
    # 查看 master 进程号
    cat /var/run/nginx.pid
    ps -ef|grep nginx
    # 杀死进程
    kill -9 22671

    # 强制停止
    pkill -9 nginx

Nginx重启

  • 发送USR2信号,Nginx会启动一个新版本的master进程和对应工作进程。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 查看nginx进程
    [root@rocky01 nginx-1.26.2]# ps -ef|grep nginx
    root 1188 1 0 Oct29 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
    nobody 4660 1188 0 00:44 ? 00:00:00 nginx: worker process
    root 98514 73643 0 06:59 pts/1 00:00:00 grep --color=auto nginx

    # 发送USR2信号,Nginx会启动一个新版本的master进程和对应工作进程。
    [root@rocky01 nginx-1.26.2]# kill -USR2 1188

    # 向旧的Nginx主进程(master)发送WINCH信号,它会逐步关闭自己的工作进程
    [root@rocky01 nginx-1.26.2]# kill -WINCH 1188

    # 发送QUIT信息
    [root@rocky01 nginx-1.26.2]# kill -QUIT 1188

Nginx配置文件

Nginx主配置文件/etc/nginx/nginx.conf是一个纯文本类型的文件,整个配置文件是以区块的形式组织的。一般,每个区块以一对大括号{}来表示开始与结束。

  • Main位于nginx.conf配置文件的最高层
  • Main层下可以有Event、HTTP层
  • HTTP层下面有允许有多个Server层, 用于对不同的网站做不同的配置
  • Server层也允许有多个Location, 用于对不同的路径进行不同模块的配置
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
//nginx默认配置语法
worker_processes //工作进程, 配置和CPU个数保持一致
error_log //错误日志, 后面接入的是路径
pid //Nginx服务启动时的pid

//events事件模块
events { //事件模块
worker_connections 1024; //每个worker进程支持的最大连接数
use //内核模型,select,poll,epoll
}

//非虚拟主机的配置或公共配置定义在http{}段内, server{}段外
http {
...
//必须使用虚拟机配置站点, 每个虚拟机使用一个server{}段
server {
listen 80; //监听端口, 默认80
server_name localhost; //提供服务的域名或主机名

//控制网站访问路径
location / {
root /usr/share/nginx/html; //存放网站路径
index index.html index.htm; //默认访问首页文件
}
//错误页面,统一定义错误页面
//定义请求错误, 指定错误代码

则。
error_page 500 502 503 504 /50x.html;
//错误代码重定向到新的Locaiton
location = /50x.html {
root html;
}
}
...
//第二个虚拟主机配置
server {
...
}
}

Nginx状态监控

编译命令添加 --with-http_stub_status_module

记录Nginx客户端基本访问状态信息

1
2
3
Syntax: stub_status;
Default: —
Context: server, location

具体配置如下:

1
2
3
4
5
6
7
8
server {
listen 9600;
location / {
root html;
access_log logs/mine_access.log main_format;
stub_status on;
}
}

访问链接

1
2
3
4
5
6
7
8
9
10
11
12
Active connections:2    //Nginx当前活跃连接数
server accepts handled requests
5 5 3


server表示Nginx启动到现在共处理了5个连接。
accepts表示Nginx启动到现在共成功创建5次握手。
请求丢失数=(握手数-连接数)可以看出,本次状态显示没有丢失请求。
handled requests,表示总共处理了3次请求。
Reading Nginx读取到客户端的 Header 信息数。
Writing Nginx返回给客户端的 Header 信息数。
Waiting Nginx开启keep-alive长连接情况下, 既没有读也没有写, 建立连接情况

Nginx下载站点

Nginx默认是不允许列出整个目录浏览下载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Syntax: autoindex on | off;
Default: autoindex off;
Context: http, server, location

# autoindex常用参数
# autoindex_exact_size off;
默认为on, 显示出文件的确切大小,单位是bytes。
修改为off,显示出文件的大概大小,单位是kB或者MB或者GB。

# autoindex_localtime on;
默认为off,显示的文件时间为GMT时间。
修改为on, 显示的文件时间为文件的服务器时间。

# charset utf-8,gbk;
默认中文目录乱码,添加上解决乱码。

配置目录浏览功能

1
2
3
4
5
6
7
8
9
10
11
12
13


server {
listen 9600;
location /nginx-1.26.2 {
root /soft;
access_log logs/mine_access.log main_format;
# 开启目录浏览
autoindex on;
autoindex_localtime on;
autoindex_exact_size off;
}
}

TCP连接

  • 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。

  • 建立起一个TCP连接需要经过“三次握手”:

    1. 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    2. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
  • 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连 接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写 了,就是服务器和客户端交互,最终确定断开)

  • 查看当前的tcp连接数

    1
    2
    3
    4
    5
    6
    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
    CLOSE_WAIT 1 # 我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT
    ESTABLISHED 9 # 建立连接。表示两台机器正在通信

    TIME_WAIT # 我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT
    # 处于TIME_WAIT状态的连接占用的资源不会被内核释放,所以作为服务器,在可能的情况下,尽量不要主动断开连接,以减少TIME_WAIT状态造成的资源浪费。

HTTP连接

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。TCP就是单纯建立连接,不涉及任何我们需要请求的实际数据,简单的传输。http是用来收发数据,即实 际应用上来的。

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

  • 在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
  • 在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

由 于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客 户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

Http协议是建立在TCP协议基础之上的,当浏览器需要从服务器获取网页数据的时候,会发出一次Http请求。Http会通过TCP建立起一个到服务器的连接通道(三次握手),当本次请求需要的数据完毕后,Http会立即将TCP连接断开,这个过程是很短的,所以Http连接是一种短连接,是一种无状态的连接。

http协议的连接与请求: HTTP是建立在TCP, 在完成HTTP请求需要先建立TCP三次握手(称为TCP连接),在连接的基础上再进行HTTP请求。HTTP请求建立在一次TCP连接基础上,一次TCP请求至少产生一次HTTP请求

连接频率限制 limit_conn_module

请求频率限制 limit_req_module



HTTP协议版本 连接关系
HTTP1.0 TCP不能复用
HTTP1.1 顺序性TCP复用
HTTP2.0 多路复用TCP复用

压力测试工具ab

  • Apache Bench 是 Apache 服务器自带的一个web压力测试工具,简称 ab 。

    1
    2
    3
    4
    5
    6
    7
    # 安装 
    yum install -y httpd-tools
    # 测试安装是否成功:
    [root@rocky01 nginx-1.26.2]# ab -V
    This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/
  • 参数介绍:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    格式:ab [options] [http://]hostname[:port]/path

    下面是参数

    -n requests Number of requests to perform //本次测试发起的总请求数
    -c concurrency Number of multiple requests to make   //一次产生的请求数(或并发数)
    -t timelimit Seconds to max. wait for responses    //测试所进行的最大秒数,默认没有时间限制。
    -r Don't exit on socket receive errors. // 抛出异常继续执行测试任务
    -p postfile File containing data to POST   //包含了需要POST的数据的文件,文件格式如“p1=1&p2=2”.使用方法是 -p 111.txt

    -T content-type Content-type header for POSTing
    // POST 数据所使用的 Content-type 头信息,如 -T “application/x-www-form-urlencoded” 。 (配合-p)

    -v verbosity How much troubleshooting info to print
    //设置显示信息的详细程度 – 4或更大值会显示头信息, 3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。 -V 显示版本号并退出。

    -C attribute Add cookie, eg. -C “c1=1234,c2=2,c3=3” (repeatable)

    //-C cookie-name=value 对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复,用逗号分割。
    提示:可以借助session实现原理传递 JSESSIONID参数, 实现保持会话的功能,如-C ” c1=1234,c2=2,c3=3, JSESSIONID=FF056CD16DA9D71CB131C1D56F0319F8″ 。

    -w Print out results in HTML tables  //以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
    -i Use HEAD instead of GET
  • 使用示例

    1
    2
    3
    4
    5
    # 参数很多,一般我们用 -n 和 -c 参数就可以了。例如:
    abs.exe -n 100 -c 20 测试网址
    # -n 后面的100,表示总共发出100 个请求;
    # -c 后面的20 ,表示采用20 个并发(模拟 20 个人同时访问),
    # 后面的网址表示测试的目标URL。
  • 运行结果:

    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
    # 对百度进行简单的压力测试: 
    [root@rocky01 nginx-1.26.2]# ab -n 100 -c 20 https://www.baidu.com/
    This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/

    Benchmarking www.baidu.com (be patient).....done

    # 被测试的Web服务器软件名称
    Server Software: BWS/1.1
    # 请求的URL主机名
    Server Hostname: www.baidu.com
    # 测试的Web服务器软件的监听端口
    Server Port: 443
    SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
    Server Temp Key: ECDH P-256 256 bits
    TLS Server Name: www.baidu.com
    # 请求的URL中的根绝对路径,通过该文件的后缀名,我们一般可以了解该请求的类型
    Document Path: /
    # HTTP响应数据的正文长度
    Document Length: 227 bytes
    # 测试的并发数
    Concurrency Level: 20
    # 请求被处理完成所花费的总时间
    Time taken for tests: 1.002 seconds
    # 总请求数量
    Complete requests: 100
    # 失败的请求数量
    Failed requests: 0
    # 整个过程中的网络传输量
    Total transferred: 139275 bytes
    # 整个过程中的HTML内容传输量
    HTML transferred: 22700 bytes
    # 最重要的指标之一,吞吐率,也叫QPS,计算公式:Complete requests/Time taken for tests,后面括号中的mean表示这是一个平均值
    Requests per second: 99.84 [#/sec] (mean)
    # 最重要的指标之二:用户平均请求等待时间,从用户角度看,完成一个请求所需要的时间。计算公式:Time token for tests/(Complete requests/Concurrency Level)。,后面括号中的mean表示这是一个平均值
    Time per request: 200.315 [ms] (mean)
    # 服务器完成一个请求的时间,计算公式:Time taken for tests/Complete requests,正好是吞吐率的倒数。
    也可以这么统计:Time per request/Concurrency Level。
    Time per request: 10.016 [ms] (mean, across all concurrent requests)
    # 平均每秒网络上的流量,可以帮助排除是否存在网络流量过大导致响应时间延长的问题
    Transfer rate: 135.80 [Kbytes/sec] received

    # 针对响应时间也就是第一个Time per request进行细分和统计
    # 一个请求的响应时间可以分成网络链接(Connect),系统处理(Processing)和等待(Waiting)三个部分。
    # 表中min表示最小值; mean表示平均值;
    # [+/-sd]表示标准差(Standard Deviation) ,也称均方差(mean square error),这个概念在中学的数学课上学过,表示数据的离散程度,数值越大表示数据越分散,系统响应时间越不稳定。
    # median表示中位数;
    # max当然就是表示最大值了。

    需要注意的是表中的Total并不等于前三行数据相加,因为前三行的数据并不是在同一个请求中采集到的,可能某个请求的网络延迟最短,但是系统处理时间又是最长的呢。所以Total是从整个请求所需要的时间的角度来统计的。这里可以看到最慢的一个请求花费了2ms(即100% 2 (longest request))。
    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 103 117 8.5 116 139
    Processing: 35 39 3.9 38 61
    Waiting: 35 39 3.8 38 61
    Total: 137 157 11.4 155 186

    # 描述每个请求处理时间的分布情况 80%的请求处理时间都不超过170ms
    # 第一行表示有50%的请求都是在2ms内完成的,可以看到这个值是比较接近平均系统响应时间 Time per request
    Percentage of the requests served within a certain time (ms)
    50% 155
    66% 160
    75% 164
    80% 168
    90% 172
    95% 179
    98% 184
    99% 186
    100% 186 (longest request)

Nginx访问限制

从传输层,先说下TCP连接,我们要和服务端连接TCP连接,需要通过三次连接,包括:请求,确认,建立连接。即传说中的“三次握手协议”。简单就是:请求,确认,连接。

  1. 第一次:C发送一个请求连接的位码SYN和一个随机产生的序列号给Seq,然后S收到了这些数据。
  2. 第二次:S收到了这个请求连接的位码,啊呀,有人向我发出请求了么,那我要不要接受他的请求,得实现确认一下,于是,发送了一个确认码 ACN(seq+1),和SYN,Seq给C,然后C收到了,这个是第二次连接。
  3. 第三次:C收到了确认的码和之前发送的SYN一比较,偶哟,对上了么,于是他又发送了一个ACN(SEQ+1)给S,S收到以后就确定建立连接,至此,TCP连接建立完成。

在前面客户端和应用服务器建立TCP连接之后,就需要用http协议来传送数据了,HTTP协议简单来说,还是请求,确认,连接。

  • 总体就是C发送一个HTTP请求给S,S收到了这个http请求,然后返回给C http响应,然后C的中间件或者说浏览器把这些数据渲染成为了网页,展示在用户面前。

  • 第一:发送一个http请求给S,这个请求包括请求头和请求内容:

    • request header:1.请求的方法是POST/GET,请求的URL,http协议版本 2.请求的数据,和编码方式 3是否有cookie和cooies,是否缓存等。
    • post和get请求方式的区别是,get把请求内容放在URL后面,但是URL长度有限制。而post是以表单的形势,适合要输入密码之类的,因为不在URL中显示,所以比较安全。
    • request body:即请求的内容.
  • 第二:S收到了http请求,然后根据请求头,返回http响应。

    • response header: 1.cookies或者sessions 2.状态吗 3.内容大小等
    • response body:即响应的内容,包括,JS什么的。
  • 第三,C收到了以后,就由浏览器完成一系列的渲染,包括执行JS脚本等。

HTTP协议版本 连接关系
HTTP1.0 TCP不能复用
HTTP1.1 顺序性TCP复用
HTTP2.0 多路复用TCP复用

限制连接数 (limit_conn)

限制连接数(limit_conn)是一种用于管理客户端与服务器之间的连接数量的方法,目的是防止服务器过载或遭受滥用攻击。在Nginx中,我们可以使用limit_conn模块来实现这种连接数限制。下面将详细介绍如何配置和工作原理。

  • limit_conn_zone的配置语法: 全局定义连接限制

    1
    2
    3
    4
    5
    6
    7
    8
    Syntax:limit_conn_zone key zone=name:size; 
    # limit_conn_zone表示申请的连接存储空间。
    # key 表示连接以哪个作为key,例如以客户端的ip作为key,限制的就是客户端的ip。
    # zone=name表示申请的存储空间的名称。size表示申请的存储空间的大小

    Default:—— 表示默认没有配置

    Context: http
  • limit_conn的配置语法: 引用连接限制

    1
    2
    3
    4
    5
    6
    7
    Syntax:limit_conn zone number;
    # zone表示limit_conn_zone中申请的存储空间的名称,
    # number表示并发请求的限制,即同一时间限制连接数

    Default:—— 表示默认没有配置

    Context:http,server,location 表示需要在http块或server块或location块中进行配置
  • 具体配置如下: http段配置连接限制, 同一时刻只允许一个客户端IP连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    http {
    # 创建了一个名为 conn_zone 的区域,最大连接数为10。这意味着每个不同的客户端IP地址最多可以建立10个连接。
    limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
    ...
    server {
    # 这将指定一个地址只能同时存在一个连接。“conn_zone”与上面的对应,也可以自定义命名
    limit_conn conn_zone 1;

    limit_rate 300k;
    # 对每个连接限速300k. 注意,这里是对连接限速,而不是对IP限速。
    # 如果一个IP允许两个并发连接,那么这个IP就是限速limit_rate×2。
    listen 9600;
    location / {
    root html;
    access_log logs/mine_access.log main_format;

    }
    }
    }
  • 压测分析: Connect中mean为1

    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
    [root@rocky01 nginx-1.26.2]# ab -n 50 -c 20  http://127.0.0.1:9600/
    This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/

    Benchmarking 127.0.0.1 (be patient).....done


    Server Software: nginx/1.26.2
    Server Hostname: 127.0.0.1
    Server Port: 9600

    Document Path: /
    Document Length: 615 bytes

    Concurrency Level: 20
    Time taken for tests: 0.005 seconds
    Complete requests: 50
    Failed requests: 0
    Total transferred: 42400 bytes
    HTML transferred: 30750 bytes
    Requests per second: 10239.61 [#/sec] (mean)
    Time per request: 1.953 [ms] (mean)
    Time per request: 0.098 [ms] (mean, across all concurrent requests)
    Transfer rate: 8479.67 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 1 0.1 1 1
    Processing: 0 1 0.2 1 1
    Waiting: 0 0 0.2 0 1
    Total: 1 2 0.3 2 2

    Percentage of the requests served within a certain time (ms)
    50% 2
    66% 2
    75% 2
    80% 2
    90% 2
    95% 2
    98% 2
    99% 2
    100% 2 (longest request)

现在让我们深入了解limit_conn模块的工作原理:

  1. 当一个客户端请求到达Nginx服务器时,Nginx会提取客户端的IP地址(通常是$binary_remote_addr)。
  2. Nginx将客户端的IP地址与之前定义的limit_conn_zone区域进行匹配。如果在该区域中没有找到客户端IP地址的条目,Nginx会创建一个新的条目,并将该IP地址与连接数计数器关联。
  3. 如果连接数计数器小于或等于允许的最大连接数(在这个示例中是10),Nginx将允许该连接继续处理。否则,Nginx将拒绝该连接并返回适当的错误响应给客户端。
  4. 当连接完成或被关闭时,Nginx会减少与该连接关联的连接数计数器。

这样,通过使用limit_conn模块,Nginx可以有效地控制每个客户端IP地址可以建立的连接数量,从而保护服务器免受连接数过多的威胁,确保服务器资源得以合理利用。

总结起来,limit_conn模块允许您配置服务器上允许的最大连接数,并根据客户端的IP地址对连接进行计数和限制。这有助于维护服务器的稳定性和安全性,特别是在面对连接数过多的情况下。

限制请求数(limit_req)

Nginx的limit_req模块用于限制客户端对服务器的请求速率,以防止服务器过载或恶意攻击。这个模块允许你设置每个客户端可以发送的请求数的上限。

  • limit_req_zone的配置语法

    1
    2
    3
    4
    5
    6
    7
    8
    Syntax:limit_req_zone key zone=name:size rate=rate [sync];

    # limit_req_zone表示申请的连接存储空间。
    # key 表示连接以哪个作为key,例如以客户端的ip作为key,限制的就是客户端的ip。
    # zone=name表示申请的存储空间的名称。size表示申请的存储空间的大小。10r/m 六秒才处理一次请求
    # rate表示请求的限制是多大,指的是一个限制的单位(以秒为单位)
    Default:—— 表示默认没有配置
    Context:http 表示需要在http块中进行配置
  • limit_req的配置语法

    1
    2
    3
    4
    5
    6
    7
    Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
    # zone=name表示limit_req_zone中申请的存储空间的名称;
    # burst = number表示超过了设置的速率以后,遗留的请求数量放到下一秒执行;
    Default:—— 表示默认没有配置
    Context:http,server,location 表示需要在http块或server块或location块中进行配置
    nodelay:如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)
    如果没有设置,则所有请求会依次等待排队
  • limit_req配置示例: 以下是一个具体的场景和相应的Nginx配置,用于限制请求速率。假设你的网站每秒最多只能处理10个请求,超过这个速率的请求将被延迟或拒绝。

    • limit_req_zone指令定义了一个速率限制区域(zone)。这个区域用于存储客户端IP地址的请求计数信息,以及限制请求的速率

    • key:Nginx内置变量$binary_remote_addr,该变量以二进制形式表示客户端的IP地址。这种表示方式相比$remote_addr(以文本形式表示IP地址)更加节省内存。使用$binary_remote_addr则意味着将每个唯一的用户IP作为限制速率的判断依据。

    • zone:定义了共享内存区域的名称和大小。将信息存储在共享内存中, 的好处在于多个Nginx worker进程可以共享这些信息。例如zone=limit_per_ip:10m表示一个名为limit_per_ip、大小为10MB的共享内存区域。当存储空间耗尽的时候,如果需要记录新的值,那么就会通过LRU算法移除旧的变量来腾出空间,如果这样腾出来的空间还是不足以接纳新的记录值,那么nginx就会返回状态码503(ServiceTemporarily``Unavailable)。此外,为了防止内存耗尽,nginx每次创建一个新记录值的时候就会清理掉两个60秒内没被使用过的旧记录值。

    • rate:指定允许的最大请求速率。在本例中,我们设置为每秒允许10个请求(10r/s)。Nginx以毫秒级别的粒度来控制请求速率,因此10r/s实际上是1r/100ms,这意味着如果在前一个请求处理后的100毫秒内出现第二个请求,它将被拒绝处理。

  • 使用limit_req指令来启用上述定义的限速参数,我们将请求速率限制应用于/路径

    • burst=5:重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有20个,超过的请求会直接报503的错误然后返回

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      http {
      # 定义请求速率限制区域,将客户端IP地址映射到一个区域中
      limit_req_zone $binary_remote_addr zone=limit_per_ip:10m rate=10r/s;
      server {
      listen 9600;
      server_name yourwebsite.com;
      location / {
      # 启用请求速率限制,引用之前定义的区域
      limit_req zone=limit_per_ip burst=5;
      # 其他配置项,例如代理请求到后端应用程序
      }
      }
      }
  • 请注意,limit_req模块非常有用,特别是在防止DDoS攻击或恶意请求时,可以帮助我们保护服务器的稳定性和可用性。根据我们的实际需求,可以根据具体情况调整速率限制参数以适应不同的流量情况。

  • 对于limit_req 还有更高级的一些用法,推荐阅读nginx 官方的这篇博文:https://www.nginx.com/blog/rate-limiting-nginx/

  • limit_req模块的工作原理: limit_req模块基于令牌桶算法来限制请求速率。它会为每个客户端IP地址维护一个令牌桶,每个令牌代表一个可以被处理的请求。令牌桶以一定的速率(例如每秒N个令牌)填充。当一个请求到达时,会尝试从令牌桶中获取一个令牌。如果令牌桶中没有足够的令牌,请求就会被延迟或拒绝,直到有足够的令牌为止。

  • 压力测试

    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
    # 发起10个并发请求
    ab -n 100 -c 10 http://127.0.0.1:9600/
    # 可以看到一共100 个请求,94个请求都失败了。且0.501秒就完成了压测

    1r/100ms

    Time taken for tests: 0.501 seconds
    Complete requests: 100
    Failed requests: 94
    (Connect: 0, Receive: 0, Length: 94, Exceptions: 0)
    Non-2xx responses: 94
    Total transferred: 39774 bytes
    HTML transferred: 22208 bytes
    Requests per second: 199.55 [#/sec] (mean)
    Time per request: 50.114 [ms] (mean)
    Time per request: 5.011 [ms] (mean, across all concurrent requests)
    Transfer rate: 77.51 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.1 0 0
    Processing: 0 15 73.1 0 500
    Waiting: 0 15 73.1 0 500
    Total: 0 15 73.1 0 500

    Percentage of the requests served within a certain time (ms)
    50% 0
    66% 0
    75% 0
    80% 0
    90% 0
    95% 101
    98% 402
    99% 500
    100% 500 (longest request)

限制响应速度(limit_rate)

limit_rate指令用于在location块内设置响应速率限制。,它通过限制服务器向客户端发送响应数据的速率,有助于维持服务器的稳定性、防止过度消耗带宽、提高服务质量,并对恶意下载行为进行限制。通过合理配置limit_rate,管理员可以更好地管理服务器资源,确保服务器正常运行。与其他Nginx限速功能,如限制请求数(limit_req)和限制连接数(limit_conn)结合使用,可以提高服务器的安全性和性能。

  • 配置limit_rate指令,示例中,我们将响应速率限制为每秒100KB。这意味着服务器将以每秒100KB的速率向客户端发送响应数据。

    1
    2
    3
    4
    5
    6
    7
    8
    http {
    server {
    location / {
    limit_rate 100k;
    # 其他配置
    }
    }
    }
  • 工作原理

  1. 当客户端发起一个请求并Nginx开始响应时,Nginx会检查请求对应的location块中是否有设置了limit_rate指令。
  2. 如果有设置limit_rate指令,Nginx会根据指定的速率限制向客户端发送响应数据。在上面的示例中,限制为每秒100KB。
  3. Nginx会定期检查已发送的数据量,以确保不超过指定的速率限制。如果发送速率超过了限制,Nginx会暂停发送数据,直到速率再次在允许范围内。
  4. 当响应数据完全发送给客户端或连接关闭时,速率限制将不再适用。

通过这种方式,Nginx可以控制响应数据的发送速率,确保服务器资源合理利用,防止过快的数据传输,以及降低网络拥塞的风险。

连接限制没有请求限制有效?

我们前面说过, 多个请求可以建立在一次的TCP连接之上, 那么我们对请求的精度限制,当然比对一个连接的限制会更加的有效。
因为同一时刻只允许一个连接请求进入。
但是同一时刻多个请求可以通过一个连接进入。
所以请求限制才是比较优的解决方案。

Nginx访问控制

基于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
//允许配置语法
Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
//拒绝配置语法
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except

//配置拒绝某一个IP, 其他全部允许
//以1.html开头的的正则匹配
// ~ 是不忽略大小写
location ~ ^/1.html {
root /usr/share/nginx/html;
index index.html;
deny 192.168.2.1;
allow all;
}

//只允许某一个网段访问,其它全部拒绝
location / {
root html;
index index.php index.html index.htm;
allow 192.168.2.0/24;
deny all;
}
  • http_access_module局限性

  • 解决方式

    1. 采用HTTP头信息控制访问, 代理以及web服务开启http_x_forwarded_for
    2. 结合geo模块作
    3. 通过HTTP自动以变量传递

基于用户登陆认证

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
# 配置语法
Syntax: auth_basic string| off;
Default: auth_basic off;
Context: http, server, location, limit_except

# 用户密码记录配置文件
Syntax: auth_basic_user_file file;
Default: -
Context: http, server, location, limit_except

# 需要安装依赖组件
[root@fl ~]# yum install httpd-tools
[root@fl ~]# htpasswd -c /etc/nginx/auth_conf zhanshan
继续添加使用-b ,使用-c会覆盖原来
htpasswd -c /etc/nginx/auth_conf zhanshan 123456

//可在http,server,location下添加如下信息
auth_basic "Auth access Blog Input your Passwd!";
auth_basic_user_file /etc/nginx/auth_conf;

# 给下载页面添加权限认证
location /down {
root /soft/package/src;
autoindex on;
autoindex_localtime on;
autoindex_exact_size off;
charset utf-8;
auth_basic "Auth access Blog Input your Passwd!";
auth_basic_user_file /etc/nginx/auth_conf;
}

  • 用户认证局限性
    1. 用户信息依赖文件方式<
    2. 操作管理机械,效率低下
  • 解决办法
    1. Nginx结合LUA实现高效验证
    2. Nginx结合LDAP, 利用nginx-auth-ldap模块

Nginx虚拟主机

Nginx虚拟主机配置主要涉及在Nginx的配置文件中定义多个server块,每个server块代表一个虚拟主机,可以配置不同的域名、根目录等。

基于IP的虚拟主机

在nginx正常安装启动后,我们就可以通过服务器的IP进行正常的访问,一般情况下配置无需更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
http {  
# ... 其他配置 ...

server {
listen 80;
server_name localhost;


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


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

# ... 其他http块配置 ...
}

基于域名的虚拟主机配置

  • 修改配置文件,添加新的server配置段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [root@RockyLinux9 nginx]# vim conf/nginx.conf


    http {
    # ... 其他配置 ...

    server {
    listen 80;
    server_name fulsun.com;

    location / {
    root html/fulsun.com;
    # 这里可以使用相对路径和绝对路径
    # 使用绝对路径可自定义其他目录
    #root /usr/local/nginx/html/fulsun.com;
    index index.html;
    }
    }

    # ... 其他http块配置 ...
    }
  • 重载配置文件

    1
    [root@RockyLinux9 nginx]# nginx -s reload
  • 创建对应的html文件

    1
    2
    3
    4
    5
    6
    7
    [root@RockyLinux9 nginx]# pwd
    /usr/local/nginx
    [root@RockyLinux9 nginx]# mkdir html/fulsun.com
    [root@RockyLinux9 nginx]# cat html/fulsun.com/index.html
    <html>
    This Web is fulsun.com.
    </html>
  • 通过IP正常访问Web 打印 This Web is fulsun.com.

  • windows访问,修改hosts文件,添加域名解析,通过域名访问Web

    1
    2
    # 默认位置:C:\Windows\System32\drivers\etc
    192.168.199.152 fulsun.com

基于域名+端口的虚拟主机配置

  • 修改配置文件,添加新的server配置段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    [root@RockyLinux9 nginx]# vim conf/nginx.conf


    http {
    # ... 其他配置 ...
    server {
    listen 8080;
    server_name fulsun.com;


    location / {
    root /usr/local/nginx/html/fulsun8080.com;
    index index.html;
    }
    }
    # ... 其他http块配置 ...
    }

    # 重载配置文件
    [root@RockyLinux9 nginx]# nginx -s reload
  • 创建对应的html文件

    1
    2
    3
    4
    5
    [root@RockyLinux9 nginx]# mkdir html/fulsun8080.com/
    [root@RockyLinux9 nginx]# cat html/fulsun8080.com/index.html
    <html>
    This Web is fulsun's port 8080.
    </html>
  • windows访问,修改hosts文件,添加域名解析,通过域名+端口访问Web http://fulsun.com:8080

    1
    2
    # 默认位置:C:\Windows\System32\drivers\etc
    192.168.199.152 fulsun.com

所谓虚拟主机,在web服务器里是一个独立的网站站点,这个站点对应独立的域名(也可能是IP或端口),具有独立的程序及资源目录,可以独立地对外提供服务供用户访问。

  • 配置基于域名虚拟主机

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 1.创建web站点目录
    [root@LNMP conf]# mkdir /soft/code/{www,bbs}
    [root@LNMP conf]# echo "www" > /soft/code/www/index.html
    [root@LNMP conf]# echo "bbs" > /soft/code/bbs/index.html
    # 2.配置虚拟主机
    [root@LNMP conf]# cat conf.d/{www,bbs}.conf
    server {
    listen 80;
    server_name www.fl.com;
    root /soft/code/www;
    ...
    }

    server {
    ...
    listen 80;
    server_name bbs.fl.com;
    root /soft/code/bbs;
    }
  • 配置不同端口访问不同虚拟主机

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //仅修改listen监听端口即可, 但不能和系统端口发生冲突
    server {
    ...
    listen 8001;
    ...
    }

    server {
    ...
    listen 8002;
    ...
    }
  • 配置虚拟主机别名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    所谓虚拟主机别名,就是虚拟主机设置除了主域名以外的一个域名,实现用户访问的多个域名对应同一个虚拟主机网站的功能。
    以www.fl.com域名的虚拟主机为例:
    为其增加一个别名fl.com时,出现网站内容和访问www.fl.com是一样的,具体配置如下:
    //默认配置
    [root@LNMP ~]# vim /etc/nginx/nginx.conf
    server {
    listen 80;
    server_name www.fl.com;
    }
    //别名配置
    [root@LNMP ~]# vim /etc/nginx/nginx.conf
    server {
    listen 80;
    server_name www.fl.com fl.com;
    ...
    }
    //使用Linux下curl测试结果
    [root@LNMP conf]# curl fl.com
    www.fl.com
    [root@LNMP conf]# curl www.fl.com
    www.fl.com
    //访问带www和不带www是一样的, 除了别名实现也可以通过rewrite实现

附录

五分钟学Nginx 限速原理与配置