nginx_进阶

5
[[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了;

[[nginx相关问题整理]]

[[LNMP]]