nginx_进阶
[[nginx基础篇]]
autoindex
server {
listen 80; # 监听 80 端口
server_name _; # 服务器名称,接收所有请求
location / {
root /mirror; # 设置根目录为 /mirror
autoindex on; # 开启目录列表功能
autoindex_exact_size on; # 显示文件的实际大小
autoindex_localtime on; # 显示本地时间而不是 UTC 时间
charset utf-8; # 设置字符集为 UTF-8
}
}
- docker 运行命令
docker run -d --name my-nginx -p 80:80 -v /path/to/nginx/conf.d:/etc/nginx/conf.d -v /path/to/nginx/html:/usr/share/nginx/html nginx
连接数监控
server{
listen 9999;
server_name _;
stub_status on;
access_log off;
}
- 浏览器访问9999即可看到
![[Pasted image 20241223110403.png]]
Active connections
# 当前活动客户端连接数,包括waiting连接数
accepts
# 接受的客户端连接总数
handled
# 处理的连接总数
requests
# 客户端请求的总数
reading
# nginx正在读取请求标头的当前连接数
writing
# nginx将响应写回客户端的当前连接数
waiting
# 当前等待请求的空闲客户端连接数
# 注意
一个tcp连接,可以发起多个http请求
可以通过修改保持连接参数修改
keepealive_timeout 0;表示关闭长连接
- 可以用ab测试下
ab -c 100 -n 200000 http://172.16.40.231:9999/
- 注意最后那个/ 一定要加
基于ip的限制访问
server {
listen 22222;
server_name _;
location / {
allow 172.16.50.0/24;
deny all;
root /www/deny_allow;
index index.html;
}
}
- 这是两道墙;匹配到第一道后后面的就不匹配了,所以50网段的可以访问,其他网段403;可以用curl测试;
- 只有allow的话没有任何意义
基于auth的认证限制
yum install httpd-tools -y
htpasswd -b -c /etc/nginx/auth_passwd zhaoxi zhaoxi666 # -b 免交互 直接输入账密 -c 设置密码写入到什么文件
cat /etc/nginx/auth_passwd
vim /etc/nginx/conf.d/auth_passwd.conf
server {
listen 3333;
server_name _;
charset utf-8;
location / {
auth_basic "please input your account and passwd";
auth_basic_user_file /etc/nginx/auth_passwd;
root /nginx/html;
index index.html;
}
}
![[Pasted image 20241224091333.png]]
限流
- 防ddos的 一般不从nginx做 后端从程序做,知道就行
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
listen 33355;
server_name _;
charset utf-8;
access_log /var/log/nginx/limit_req.log;
limit_req zone=one burst=3 nodelay;
location / {
root /nginx/limit_html;
index index.html;
}
}
- 测试 200:
# tx:
[root@tx_yun ~] for i in {1..10};do curl 115.120.218.18:33355;sleep 1;done
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
# hw:
[root@hw ~] tail -f /var/log/nginx/limit_req.log
124.223.143.167 - - [24/Dec/2024:00:26:57 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:26:58 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:26:59 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:00 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:01 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:02 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:03 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:04 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:05 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:27:06 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
- 测试 503:
# tx:
[root@tx_yun ~] for i in {1..10} ; do curl 115.120.218.18:33355 ; sleep 0.5 ; done
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
限速控制
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>
限速控制
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>
# hw:
> /var/log/nginx/limit_req.log
[root@hw ~] tail -f /var/log/nginx/limit_req.log
124.223.143.167 - - [24/Dec/2024:00:30:52 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:52 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:53 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:53 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:54 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:54 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:55 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:55 +0800] "GET / HTTP/1.1" 503 197 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:56 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0"
124.223.143.167 - - [24/Dec/2024:00:30:56 +0800] "GET / HTTP/1.1" 503 197 "-" "curl/7.29.0"
- 注意看vip次数 是3次 所以第三次异常请求的时候就开始报503;
内置变量
https://nginx.org/en/docs/http/ngx_http_core_module.html
- 网页自己看吧
- 如果两个server 端口是一样的,server_name不一样 会自上而下去匹配server_name;
开启第三方模块
- nginx如果安装好了再想添加只能重新编译安装;
小插曲:
server {
location / { # 这里的/是最低级别匹配,比如zaox.site/hell;zaox.site/hehe.html
...
}
}
重新编译安装:
# 下载nginx源码
yum install pcre pcre-devel openssl openssl-devel zlib zlib-devel gzip gcc gcc-c++ make wget httpd-tools vim -y
groupadd www -g 666
useradd www -u 666 -g 666 -M -s /sbin/nologin
cd /opt/
wget http://nginx.org/download/nginx-1.19.0.tar.gz
tar -zxf nginx-1.19.0.tar.gz
# 下载第三方模块源码(echo)
yum install git -y
git clone https://github.com/openresty/echo-nginx-module.git
# 开始编译(编译三部曲) 有一些not found报错没事,生成Makefile就行
1. ./configure --user=www --group=www --prefix=/opt/nginx-1-19-0 --with-http_stub_status_module --with-http_ssl_module --with-pcre --add-module=/opt/echo-nginx-module-master
2.3. make && make install
测试验证:
[root@hw /opt/nginx-1-19-0] sbin/nginx -v
nginx version: nginx/1.19.0
[root@hw /opt/nginx-1-19-0] sbin/nginx -V
nginx version: nginx/1.19.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/opt/nginx-1-19-0 --with-http_stub_status_module --with-http_ssl_module --with-pcre --add-module=/opt/echo-nginx-module-master/
# 更新配置文件
grep -Ev '^$|#' nginx.conf # 小技巧
-E 等价于egrep 以后用egrep吧
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 自定义配置文件优化 自己设置
include /opt/nginx-1-19-0/conf/conf.d/*.conf;
}
mkdir conf.d
vim conf.d/test_echo.conf
server {
listen 11444;
server_name localhost;
charset utf-8;
location / {
echo "carl welcome you!";
echo $uri;
echo $document_uri;
echo $remote_addr;
echo $remote_port;
echo $http_user_agent;
}
}
[root@hw /opt/nginx-1-19-0] sbin/nginx -t
[root@hw /opt/nginx-1-19-0] sbin/nginx
[root@hw /opt/nginx-1-19-0] netstat -tunlp | grep 11444
tcp 0 0 0.0.0.0:11444 0.0.0.0:* LISTEN 11945/nginx: master
测试访问:
- 你如果用浏览器去访问,nginx默认不会解析这个echo打印的内容,会提供下载功能,让你查看这些字符串
- 使用win:
![[Pasted image 20241225004324.png]] - 使用linux:
![[Pasted image 20241225004418.png]]
location
- 根据用户请求的url不同来执行不同的应用;
- 有符号的才有优先级,否则都往后排;
| 匹配符 | 匹配规则 | 优先级 |
|---|---|---|
| = | 定义url和位置的精确匹配 | 1 |
| ^~ | 以某个字符串开头,不检查正则,区分大小写 | 2 |
| ~ | 区分大小写的正则匹配 | 3 |
| ~* | 不区分大小写的正则匹配 | 4 |
测试用例:
server {
listen 11111;
server_name _;
# 最低级匹配,不符合其他locaiton就来这
# 属于通用url规则
location / {
return 200 "location / \n";
}
# 优先级最高,等于号后面可以指定url
location = / {
return 200 "location = / \n";
}
#以/documents/开头的url,来这里,如符合其他locaiton,则以其他优先
location /documents/ {
return 200 "location /documents/ \n";
}
#匹配任何以/images/开头的请求,不匹配正则,\是转意符,代表后面只是一个.不是正则
location ^~ /images/ {
return 200 "location ^~ /images/ \n";
}
#匹配任何以.gif结尾的请求,支持正则
location ~* \.(gif|jpg|jpeg)$ {
return 200 "location ~* \.(gif|jpg|jpeg) \n";
}
access_log off;
}
测试演示:
[root@tx ~] curl hw:11111
location = / # 默认会自己带/
[root@tx ~] curl hw:11111/
location = /
[root@tx ~] curl hw:11111/test
location /
[root@tx ~] curl hw:11111/documents
location / # 必须一模一样,后面的/也不能少
[root@tx ~] curl hw:11111/documents/
location /documents/ # 这里conf里如果后面的/没写,即/documents 那curl 后面的/写不写都行
[root@tx ~] curl hw:11111/images/
location ^~ /images/
[root@tx ~] curl hw:11111/documents/images/
location /documents/ # 按理说images比documents优先级高,但是images不是开头的
[root@tx ~] curl hw:11111/test/images/
location / # images不是开头的
[root@tx ~] curl hw:11111/test/images/test.gif
location ~* \.(gif|jpg|jpeg)
[root@tx ~] curl hw:11111/test/images/tTKDSN.GIF
location ~* \.(gif|jpg|jpeg)
root | alias
root:
- 会将该url(/static)填充到网页根目录下,认为它也是一个目录,即下面的会去/nginx/static/下找图片;
server {
listen 1234;
location ^~ /static {
root /nginx;
}
}
![[Pasted image 20241225224311.png]]
错误案例:
server {
listen 1234;
location ^~ /static {
root /nginx/static;
}
}
- 会404
- 更正:
[root@hw /nginx/static] mkdir static
[root@hw /nginx/static] mv test.jpg static/
alias:
- 就是目录替换,把url替换成路径(个人认为有点类似于绝对路径,root是相对路径);
- alias /nginx/static/; 后面的/static/的/必须加,不然等着404,这是个路径替换的过程;
server {
listen 2345;
location ^~ /static {
alias /nginx/static/;
}
}
![[Pasted image 20241225225457.png]]
- 崩塌了....刚测试了alias /nginx/static; 没带/ 也能正常访问,又测试更改文件路径/nignx/static/dir/test.jpg,访问hw:2345/static/dir/test.jpg不仅没拼接错误成/nginx/staticdir/test.jpg,还访问成功了;
- 刚问了gpt是nginx做了智能处理,什么狗屁不同的玩意,不知道原理;
- 就这样吧,以后配置还是加上/吧 别出岔子;
rewrite
- url重写技术,更改请求的url
| 指令 | 解释 |
|---|---|
| break | 中断配置 |
| if | 请求判断 |
| set | 设置变量 |
| return | 返回值 |
| rewrite | 对用户请求url重写 |
if
理论
- 条件符号
| 符号 | 作用 |
|---|---|
| = | 不过多解释 |
| != | 不过多解释 |
| ~ | 区分大小写的正则匹配,匹配为true,否则为false |
| !~ | 区分大小写的正则匹配,匹配为false,否则为true |
| ~* | 不区分大小写的正则匹配,匹配为true,否则为false |
| !~* | 不区分大小写的正则匹配,匹配为false,否则为true |
- 条件参数
| 符号 | 作用 |
|---|---|
| -f和!-f | 请求的文件是否存在 |
| -d和!-d | 判断目录是否存在 |
| -e和!-e | 判断文件、目录、软连接是否存在 |
| -x和!-x | 判断请求文件是否有执行权限 |
实际用法
server {
# 客户端完全匹配到
listen 22555;
server_name localhost;
root html;
charset utf-8;
location /test-if {
# 客户端类型完全匹配到 huawei
if ($http_user_agent = huawei){
echo "agent is huawei";
}
# 客户端类型区分大小写
# 你这里的正则符号,就是一个完全的字符 ,区分大小写的字符串
# Iphone ,你只能传入 Iphone才行
# 基于正则匹配,你得写入正则符号。
if ($http_user_agent ~ Iphone) {
echo "agent is Iphone";
}
# 客户端类型不区分大小写
if ($http_user_agent ~* Chrome) {
echo "agent is Chrome";
}
# 如果请求方法不是GET就提示 ”只能用GET方法,你这个烂玩家“
if ($request_method != GET) {
echo "必须是GET方法,你这个烂玩家";
}
# 如果是IE浏览器,直接提示 "不支持IE,请下载Chrome浏览器"
# 不区分大小写的正则匹配
if ($http_user_agent ~* IE){
echo "不支持IE,请下载Chrome浏览器";
}
# 如果上面没有任何匹配,执行如下语句
echo "if规则没有匹配到";
echo "agent is >>>>>> $http_user_agent";
echo "request_method is >>>>>>>> $request_method";
}
}
测试
[root@hw /opt/nginx/conf/conf.d] curl localhost:22555/test-if
if规则没有匹配到
agent is >>>>>> curl/7.29.0
request_method is >>>>>>>> GET
[root@hw /opt/nginx/conf/conf.d] curl -A 'huawei' localhost:22555/test-if
agent is huawei
return
return code test/url;
return 200 ;
return 301 http://baidu.com;
return 404 没有资源;
set
- 自定义变量
set $my_url http://baidu.com
server {
listen 80;
server_name _;
location / {
return 301 $my_url;
}
}
break
- break是专门用于终止,rewrite的其他指令的执行的;
- rewrite这个url重写模块,支持如下几个关键字break, if, return, rewrite, and set这些关键字都可以在server{} location中定义;
- break的作用是,nginx的代码,执行带break之后,就会停止后续的if, return, rewrite, set指令的执行;
server {
listen 22888;
server_name _;
root html;
location / {
set $my_website yuchaoit.cn;
echo "welcome to my website:" $my_website;
break;
set $my_name yuchao; # 这个set不会执行,只会下一步echo,可以测试一下;
echo "my name is" $my_name;
}
}
rewrite实战
- 除了实现域名的跳转之外,还得实现参数的保留
- permanent and redirct是在agent实现url更新
- last and break 是在serve实现url更新(client的url不会变化)
permanent(301永久跳转)
# 先建立旧网站的虚拟主机
server {
listen 30001;
server_name old301.com;
location / {
rewrite / http://new301.com:30000 permanent;
}
} # 这个/ 为正则 是实现参数保留的 这里做测试简单一点
# 建立新网站的虚拟主机
server {
listen 30000;
server_name new301.com;
location / {
alias /nginx/301/;
index index.html; # 注意给新网站配置资源
}
}
# 给客户端添加hosts 115.120.218.18 hw new301.com old301.com
- 这时候访问old301.com:30001会自动跳转到new
![[Pasted image 20250102230651.png]]
redirect(302临时跳转)
- 跟301一样 就是把rewrite的permanent换成redirect;
- 旧网站的状态码也会变成302;
last
- server 内部跳转,请求也只有1个,没有301重定向码,client无感
server {
listen 34567;
location /3 {
alias /nginx/last/;
}
location /2 {
rewrite ^/2/(.*)$ /3/$1 last;
}
location /1 {
rewrite ^/1/(.*)$ /2/$1 last;
}
}
rewrite ^/1/(.*)$ /2/$1正则,url中/1/下的任何文件前定义为1,跳转到/2/$1 并last参数;
break
server {
listen 34567;
location /3 {
alias /nginx/last/;
}
location /2 {
alias /nginx/last2/;
index index.html
rewrite ^/2/(.*)$ /3/$1 last;
}
location /1 {
rewrite ^/1/(.*)$ /2/$1 break;
}
}
- 这时候访问1就只会跳转到2的index,因为有break 就不会再走下面的rewrite了;