9. Nginx极速版-TCP反向代理
基本配置
# HTTP代理
http {
server{
# ...
}
}
# TCP代理
stream {
server {
listen 13306;
proxy_pass 192.168.164.137:33061;
}
}
TCP 负载均衡
# TCP代理
stream {
upstream backend-mysql {
server localhost:33061;
server 192.168.164.137:33061;
# [测试失败]定义连接池里空闲连接的数量
# keepalive 8;
# [测试失败]如果连接池里的连接空闲时间超过这个值,则关闭这个连接
# keepalive_timeout 30s;
}
server {
listen 13306;
proxy_pass backend-mysql;
}
}
使用 keepalive 定义连接池里空闲连接的数量。
Keepalive_timeout 默认 60 s。如果连接池里的连接空闲时间超过这个值,则连接关闭。
在最简单的 HTTP 实现中,客户端打开新连接,写入请求,读取响应,然后关闭连接以释放关联的资源。
![[image-20230819225752149.png]]
在客户端读取响应后,保持连接处于打开状态,因此可以将其重新用于后续请求。
![[image-20230819225759959.png]]
使用 keepalive 指令启用从 NGINX Plus 到上游服务器的保持活动连接,定义在每个工作进程的缓存中保留的与上游服务器的空闲保持活动连接的最大数量。当超过此数字时,将关闭最近最少使用的连接。如果没有 keepalives, 您将增加更多的开销,并且连接和临时端口都效率低下。
现代 Web 浏览器通常会打开 6 到 8 个保持连接。
重写(return 和 rewrite)
return
服务端停止处理并将状态码status code返回给客户端
return code URL
return code text
return code
return URL
强制所有请求使用Https
错误写法
server {
listen 8003;
server_name ruoyi.loadbalance;
return 301 https://localhost:8004;
}
正确写法
server {
listen 8003;
server_name ruoyi.loadbalance;
return 301 https://192.168.56.105:8004;
}
转发和重定向
转发是服务端行为,重定向是客户端行为。
转发
发向代理 proxy_pass 属于转发,浏览器的访问栏输入的地址不会发生变化。
![[image-20230819231620804.png]]
重定向
return, rewrite 属于重定向,在客户端进行。浏览器的访问栏输入的地址会发生变化。
![[image-20230819231800613.png]]
域名迁移,不让用户收藏的链接或者搜索引擎的链接失效,将请求从 www.old-name.com old-name. Com 永久重定向到 www.new-name.com ,包含 http 和 nttps 请求
server {
listen 80;
listen 443 ssl;
server_name www.old-name.com old-name.com;
return 301 $scheme://www.new-name.com$request_uri;
}
由于捕获了域名后面的 URL 部分,因此,如果新旧网站之间存在一对一的页面对应关系(例如, www.new-name.com/about 具有与 www.old-name.com/about 相同的基本内容 ),则此重写是合适的。如果除了更改域名之外还重新组织了网站,则通过省略以添加 www
# add 'www'
server {
listen 80:
listen 443 ssl;
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
}
rewrite
如果指定的正则表达式与请求 URI 匹配,则 URI 将按照字符串中的指定进行更改。指令按其在配置文件中出现的先后顺序执行。
上面是使用该指令的示例 NGINX 重写规则。它匹配以字符串 /download 开头的 URL,然后在路径后面的某个位置包含 /media/ 或 /audio/ 目录。它将这些元素替换为 /mp3/,并添加相应的文件扩展名,.mp3 或 .ra。和变量捕获未更改的路径元素。例如,/download/cdn-west/media/file1 变成了 /download/cdn-west/mp3/file1.mp3。如果文件名上有扩展名(如 .flv),则表达式会将其剥离,并将其替换为.mp3。
如果字符串包含新的请求参数,则以前的请求参数将追加到这些参数之后。如果不需要这样做,则在替换字符串的末尾放置一个问号可以避免附加它们,例如:replacement
last 与 break
- last:如果当前规则不匹配,停止处理后续 rewrite 规则,使用重写后的路径,重新搜索 location 及其块内指令
- break:如果当前规则不匹配,停止处理后续 rewrite 规则,执行{}块内其他指令
不使用last和break
在root /home/AdminLTE-3.2.0/pages下创建一个1.txt,里面内容是this is a file
server {
listen 8000;
server_name nginx-dev;
rewrite_log on;
location / {
rewrite ^/old/(.*) /new/$1;
rewrite ^/new/(.*) /pages/$1;
#根目录
root /home/AdminLTE-3.2.0;
#首页
index index.html index2.html index3.html;
}
location /pages/1.txt {
return 200 "this is rewrite test!";
}
}
默认按顺序执行。
访问 http://192.168.56.105:8000/old/1.txt
结果:this is rewrite test!
日志:
[notice] 26837#26837: *1181 "^/old/(.*)" matches "/old/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26837#26837: *1181 rewritten data: "/new/1.txt", args: "", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26837#26837: *1181 "^/new/(.*)" matches "/new/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26837#26837: *1181 rewritten data: "/pages/1.txt", args: "", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
使用break
访问 http://192.168.56.105:8000/old/1.txt
- 匹配到了 rewrite ^/old/(.*) /new/$1
- break 指令不执行后续的 rewrite 规则,以新的/new/1.txt 路径去执行块内的其他指令
- 去root目录下寻找文件, 由于不再村/home/AdminLTE-3.2.0/new/1.txt这个文件,返回404
server {
listen 8000;
server_name nginx-dev;
rewrite_log on;
location / {
rewrite ^/old/(.*) /new/$1 break;
rewrite ^/new/(.*) /pages/$1;
#根目录
root /home/AdminLTE-3.2.0;
#首页
index index.html index2.html index3.html;
}
location /pages/1.txt {
return 200 "this is rewrite test!";
}
}
访问 http://192.168.56.105:8000/old/1.txt
结果:

访问日志:
[notice] 26772#26772: *1179 "^/old/(.*)" matches "/old/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26772#26772: *1179 rewritten data: "/new/1.txt", args: "", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[error] 26772#26772: *1179 open() "/home/AdminLTE-3.2.0/new/1.txt" failed (2: No such file or directory), client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
使用last
访问 http://192.168.56.105:8000/old/1.txt
- 匹配到了 rewrite ^/old/(.*) /new/$1
- last 指令不执行后续的 rewrite 规则,以新的/new/1.txt 路径去匹配 location
- 先匹配到 location /, 有匹配到 location 里的 rewrite ^/new/(.*) /pages/$1规则,重定向到
/pages/1.txt - 匹配到了 location /pages/1.txt ,于是返回了 this is rewrite test!
server {
listen 8000;
server_name nginx-dev;
rewrite_log on;
location / {
rewrite ^/old/(.*) /new/$1 last;
rewrite ^/new/(.*) /pages/$1;
#根目录
root /home/AdminLTE-3.2.0;
#首页
index index.html index2.html index3.html;
}
location /pages/1.txt {
return 200 "this is rewrite test!";
}
}
访问 http://192.168.56.105:8000/old/1.txt
结果:this is rewrite test!
日志:
[notice] 26969#26969: *1185 "^/old/(.*)" matches "/old/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26969#26969: *1185 rewritten data: "/new/1.txt", args: "", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26969#26969: *1185 "^/old/(.*)" does not match "/new/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26969#26969: *1185 "^/new/(.*)" matches "/new/1.txt", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"
[notice] 26969#26969: *1185 rewritten data: "/pages/1.txt", args: "", client: 192.168.56.1, server: nginx-dev, request: "GET /old/1.txt HTTP/1.1", host: "192.168.56.105:8000"