Nginx基本配置
Nginx配置的核心功能说明 : Core functionality
Nginx运行命令
显示帮助信息
1 |
|
显示版本信息
1 | [root@RockyLinux9 ~]# nginx -v |
显示版本信息和编译配置项
1 | [root@RockyLinux9 ~]# nginx -V |
检查测试配置文件
1 | [root@RockyLinux9 ~]# nginx -t |
检查测试配置文件并输出内容
1 | [root@RockyLinux9 ~]# nginx -T |
在配置文件测试期间禁止显示非错误消息
1 | [root@RockyLinux9 ~]# nginx -q |
启动时指定全局配置项
(需为配置文件中未设置项),格式: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 | //nginx默认配置语法 |
Nginx状态监控
编译命令添加 --with-http_stub_status_module
记录Nginx客户端基本访问状态信息
1 | Syntax: stub_status; |
具体配置如下:
1 | server { |
访问链接
1 | Active connections:2 //Nginx当前活跃连接数 |
Nginx下载站点
Nginx默认是不允许列出整个目录浏览下载。
1 | Syntax: autoindex on | off; |
配置目录浏览功能
1 |
|
TCP连接
手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
建立起一个TCP连接需要经过“三次握手”:
- 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连 接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写 了,就是服务器和客户端交互,最终确定断开)
查看当前的tcp连接数
1
2
3
4
5
6netstat -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连接,需要通过三次连接,包括:请求,确认,建立连接。即传说中的“三次握手协议”。简单就是:请求,确认,连接。
- 第一次:C发送一个请求连接的位码SYN和一个随机产生的序列号给Seq,然后S收到了这些数据。
- 第二次:S收到了这个请求连接的位码,啊呀,有人向我发出请求了么,那我要不要接受他的请求,得实现确认一下,于是,发送了一个确认码 ACN(seq+1),和SYN,Seq给C,然后C收到了,这个是第二次连接。
- 第三次: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
8Syntax:limit_conn_zone key zone=name:size;
# limit_conn_zone表示申请的连接存储空间。
# key 表示连接以哪个作为key,例如以客户端的ip作为key,限制的就是客户端的ip。
# zone=name表示申请的存储空间的名称。size表示申请的存储空间的大小
Default:—— 表示默认没有配置
Context: httplimit_conn
的配置语法: 引用连接限制1
2
3
4
5
6
7Syntax: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
19http {
# 创建了一个名为 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模块的工作原理:
- 当一个客户端请求到达Nginx服务器时,Nginx会提取客户端的IP地址(通常是$binary_remote_addr)。
- Nginx将客户端的IP地址与之前定义的limit_conn_zone区域进行匹配。如果在该区域中没有找到客户端IP地址的条目,Nginx会创建一个新的条目,并将该IP地址与连接数计数器关联。
- 如果连接数计数器小于或等于允许的最大连接数(在这个示例中是10),Nginx将允许该连接继续处理。否则,Nginx将拒绝该连接并返回适当的错误响应给客户端。
- 当连接完成或被关闭时,Nginx会减少与该连接关联的连接数计数器。
这样,通过使用limit_conn模块,Nginx可以有效地控制每个客户端IP地址可以建立的连接数量,从而保护服务器免受连接数过多的威胁,确保服务器资源得以合理利用。
总结起来,limit_conn模块允许您配置服务器上允许的最大连接数,并根据客户端的IP地址对连接进行计数和限制。这有助于维护服务器的稳定性和安全性,特别是在面对连接数过多的情况下。
限制请求数(limit_req)
Nginx的limit_req模块用于限制客户端对服务器的请求速率,以防止服务器过载或恶意攻击。这个模块允许你设置每个客户端可以发送的请求数的上限。
limit_req_zone的配置语法
1
2
3
4
5
6
7
8Syntax: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
7Syntax: 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(Service
Temporarily``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
13http {
# 定义请求速率限制区域,将客户端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
8http {
server {
location / {
limit_rate 100k;
# 其他配置
}
}
}工作原理
- 当客户端发起一个请求并Nginx开始响应时,Nginx会检查请求对应的location块中是否有设置了limit_rate指令。
- 如果有设置limit_rate指令,Nginx会根据指定的速率限制向客户端发送响应数据。在上面的示例中,限制为每秒100KB。
- Nginx会定期检查已发送的数据量,以确保不超过指定的速率限制。如果发送速率超过了限制,Nginx会暂停发送数据,直到速率再次在允许范围内。
- 当响应数据完全发送给客户端或连接关闭时,速率限制将不再适用。
通过这种方式,Nginx可以控制响应数据的发送速率,确保服务器资源合理利用,防止过快的数据传输,以及降低网络拥塞的风险。
连接限制没有请求限制有效?
我们前面说过, 多个请求可以建立在一次的TCP连接之上, 那么我们对请求的精度限制,当然比对一个连接的限制会更加的有效。
因为同一时刻只允许一个连接请求进入。
但是同一时刻多个请求可以通过一个连接进入。
所以请求限制才是比较优的解决方案。
Nginx访问控制
基于IP的访问控制
1 | //允许配置语法 |
http_access_module局限性
解决方式
- 采用HTTP头信息控制访问, 代理以及web服务开启
http_x_forwarded_for
- 结合geo模块作
- 通过HTTP自动以变量传递
- 采用HTTP头信息控制访问, 代理以及web服务开启
基于用户登陆认证
1 | # 配置语法 |
- 用户认证局限性
- 用户信息依赖文件方式<
- 操作管理机械,效率低下
- 解决办法
- Nginx结合LUA实现高效验证
- Nginx结合LDAP, 利用
nginx-auth-ldap
模块
Nginx虚拟主机
Nginx虚拟主机配置主要涉及在Nginx的配置文件中定义多个server
块,每个server
块代表一个虚拟主机,可以配置不同的域名、根目录等。
基于IP的虚拟主机
在nginx正常安装启动后,我们就可以通过服务器的IP进行正常的访问,一般情况下配置无需更改。
1 | 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实现