nginx 原理+实战

1.简介

1.1概念

image-20231115152245344

1.2特点

在这里插入图片描述

1.3nginx架构

在这里插入图片描述

1.4nginx关键工作机制

  • 抢占机制:当客户端发起请求时,会激活accept_mutex互斥锁,那个worker抢占了该互斥锁,该客户端的请求就由那个worker响应和处理
    在这里插入图片描述
  • 异步非阻塞模式:在传统事件处理模式下,如果所有的worker被客户端阻塞后,新来的客户就需要等待,直到原来的客户端释放worker后才能被处理请求,在异步非阻塞模式下,底层使用了linux的epoll模型,就算worker被阻塞,新的客户端请求也会被正常处理
    image-20231115154156618

1.5nginx正向代理功能

image-20231116085553280
分析:它的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我,从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

理解:
客户端 <一> 代理 <一> 服务端
A租房人(客户端) B房产中介(代理) C真实房东(服务端)

1.6nginx反向代理功能

image-20231116090321087
分析:反向代理正好相反,它也是在客户端和服务器端的一个代理服务器,但是这个代理服务器的目的是用来保护服务器端的,当外网客户端来访问我们的服务器时为了避免暴露应用服务器的实际ip地址,我们会让客端访问代理服务器,然后代理服务器再根据客户端的请求去实际的应用服务器获取响应内容并返回客户端

image-20231115154718314

1.7nginx负载均衡功能

image-20231115154752392

2.实验

2.1编译安装nginx

实验环境:
一台名为nginx的虚拟机 ip: 172.25.254.100

vmset.sh eth0 172.25.254.100 nginx.alan.org
#下载-安装
[root@Nginx ~]# yum install gcc pcre-devel zlib-devel openssl-devel -y
[root@nginx ~]# tar zxf nginx-1.24.0.tar.gz 
[root@Nginx nginx-1.24.0]# useradd -s /sbin/nologin -M nginx
[root@nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
--user=nginx \            # 指定nginx运行用户
--group=nginx \           # 指定nginx运行组
--with-http_ssl_module \  # 支持https://
--with-http_v2_module \   # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \              # 支持正则
--with-stream \            # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip

nginx完成后会出现四个目录

[root@nginx nginx-1.24.0]# ls
auto     CHANGES.ru  configure  html     Makefile  objs    src
CHANGES  conf        contrib    LICENSE  man       README
[root@nginx nginx-1.24.0]# make && make install
[root@nginx nginx-1.24.0]# ls /usr/local/nginx/
conf  html  logs  sbin
  • conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀去掉即可。
  • html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面
  • logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比
    如/var/logs/nginx里面。
  • sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。

验证版本及编译参数

[root@nginx nginx]# vi ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx nginx]# source ~/.bash_profile

显示 /usr/local/nginx/sbin/nginx 这个文件的磁盘使用量

[root@nginx nginx]# du -sh /usr/local/nginx/sbin/nginx 
5.5M    /usr/local/nginx/sbin/nginx

2.2平滑升级和回滚

2.2.1平滑升级

[root@nginx ~]# ls
anaconda-ks.cfg  echo-nginx-module-0.63.tar.gz  nginx-1.24.0  nginx-1.24.0.tar.gz  nginx-1.26.1  nginx-1.26.1.tar.gz
[root@nginx ~]# tar zxf nginx-1.26.1.tar.gz 
[root@nginx ~]# tar zxf echo-nginx-module-0.63.tar.gz 
[root@nginx ~]# ls
anaconda-ks.cfg                nginx-1.24.0         nginx-1.26.1.tar.gz
echo-nginx-module-0.63         nginx-1.24.0.tar.gz
echo-nginx-module-0.63.tar.gz  nginx-1.26.1
[root@nginx ~]# cd nginx-1.26.1
[root@nginx nginx-1.26.1]# ls
auto     CHANGES.ru  configure  html     man     src
CHANGES  conf        contrib    LICENSE  README
#检测,需要加一个模板参数
[root@nginx nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --add-module=/root/echo-nginx-module-0.63 --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
[root@nginx nginx-1.26.1]# ls
auto     CHANGES.ru  configure  html     Makefile  objs    src
CHANGES  conf        contrib    LICENSE  man       README
[root@nginx nginx-1.26.1]# make  #
[root@nginx nginx-1.26.1]# cd objs/
[root@nginx objs]# ls
autoconf.err  nginx    ngx_auto_config.h   ngx_modules.c  src
Makefile      nginx.8  ngx_auto_headers.h  ngx_modules.o
[root@nginx objs]# cd /usr/local/nginx/sbin/
[root@nginx sbin]# ls  
nginx

备份nginx

[root@nginx sbin]# cp nginx nginx.old
[root@nginx sbin]# ls
nginx  nginx.old

将新版本的nginx命令复制过去

[root@nginx sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin
[root@nginx sbin]# ps -aux | grep nginx
avahi        896  0.0  0.1  15532  6196 ?        Ss   20:18   0:00 avahi-daemon: running [nginx.local]
root        5307  0.0  0.0   9856   928 ?        Ss   21:03   0:00 nginx: master process nginx
nginx       5308  0.0  0.1  13752  5244 ?        S    21:03   0:00 nginx: worker process
root        5324  0.0  0.0 221664  2240 pts/0    S+   21:04   0:00 grep --color=auto nginx
[root@nginx sbin]# pidof nginx
5308 5307

将旧的work回收,使用新的进程

[root@nginx sbin]# kill -USR2 5307  #nginx worker ID
[root@nginx sbin]# ps -aux | grep nginx
avahi        896  0.0  0.1  15532  6196 ?        Ss   20:18   0:00 avahi-daemon: running [nginx.local]
root        5307  0.0  0.0   9856  2524 ?        Ss   21:03   0:00 nginx: master process nginx
nginx       5308  0.0  0.1  13752  5244 ?        S    21:03   0:00 nginx: worker process
root        5325  0.0  0.1   9884  6028 ?        S    21:05   0:00 nginx: master process nginx
nginx       5326  0.0  0.1  13780  4712 ?        S    21:05   0:00 nginx: worker process
root        5329  0.0  0.0 221664  2252 pts/0    S+   21:05   0:00 grep --color=auto nginx
[root@nginx sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 13:05:39 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Fri, 16 Aug 2024 13:02:49 GMT
Connection: keep-alive
ETag: "66bf4df9-267"
Accept-Ranges: bytes

向进程 ID 为 5307 的进程发送 WINCH 信号

[root@nginx sbin]#  kill -WINCH 5307
[root@nginx sbin]# ps -aux | grep nginx
avahi        896  0.0  0.1  15532  6196 ?        Ss   20:18   0:00 avahi-daemon: running [nginx.local]
root        5307  0.0  0.0   9856  2524 ?        Ss   21:03   0:00 nginx: master process nginx
root        5325  0.0  0.1   9884  6028 ?        S    21:05   0:00 nginx: master process nginx
nginx       5326  0.0  0.1  13780  4712 ?        S    21:05   0:00 nginx: worker process
root        5331  0.0  0.0 221664  2232 pts/0    S+   21:06   0:00 grep --color=auto nginx

测试

[root@nginx sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Fri, 16 Aug 2024 13:06:30 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Fri, 16 Aug 2024 13:02:49 GMT
Connection: keep-alive
ETag: "66bf4df9-267"
Accept-Ranges: bytes

2.2.2回滚

当新版本效果一般时我们如何回到老版本

[root@nginx sbin]# kill -HUP 5307
[root@nginx sbin]# ps -aux | grep nginx
avahi        896  0.0  0.1  15532  6196 ?        Ss   20:18   0:00 avahi-daemon: running [nginx.local]
root        5307  0.0  0.0   9856  2524 ?        Ss   21:03   0:00 nginx: master process nginx
root        5325  0.0  0.1   9884  6028 ?        S    21:05   0:00 nginx: master process nginx
nginx       5326  0.0  0.1  13780  5256 ?        S    21:05   0:00 nginx: worker process
nginx       5333  0.0  0.1  13752  4700 ?        S    21:06   0:00 nginx: worker process
root        5335  0.0  0.0 221664  2256 pts/0    S+   21:06   0:00 grep --color=auto nginx
​
[root@nginx sbin]# kill -WINCH 5325
[root@nginx sbin]# ps -aux | grep nginx
avahi        896  0.0  0.1  15532  6196 ?        Ss   20:18   0:00 avahi-daemon: running [nginx.local]
root        5307  0.0  0.0   9856  2524 ?        Ss   21:03   0:00 nginx: master process nginx
root        5325  0.0  0.1   9884  6028 ?        S    21:05   0:00 nginx: master process nginx
nginx       5333  0.0  0.1  13752  4700 ?        S    21:06   0:00 nginx: worker process
root        5337  0.0  0.0 221664  2252 pts/0    S+   21:07   0:00 grep --color=auto nginx

测试

[root@nginx sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 13:07:38 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Fri, 16 Aug 2024 13:02:49 GMT
Connection: keep-alive
ETag: "66bf4df9-267"
Accept-Ranges: bytes

2.3nginx核心配置详解

Nginx的配置文件的组成部分

  • 主配置文件:nginx.conf
  • 子配置文件: include conf.d/*.conf
  • fastcgi, uwsgi,scgi 等协议相关的配置文件
  • mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮
  • 件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某
  • 种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动
  • 使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

主配置文件结构:四部分

main block:主配置段,即全局配置段,对http,mail都有效
#事件驱动相关的配置
event {

}
#http/https 协议相关配置段
http {
默认的nginx.conf 配置文件格式说明

}
#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {

}
#stream 服务器相关配置段
stream {

}

2.3.1修改全局配置文件

[root@nginx ~]# vi /usr/local/nginx/conf/nginx.conf
user  nginx;
worker_processes  auto; # 进程数
worker_cpu_affinity 0001 0010 0100 1000; #绑定进程数
....
events {
    worker_connections  100000;   #支持的链接数量,取决于系统能够打开多少文件
}
.....
#gzip  on;
    include "/usr/local/nginx/conf.d/*.conf";  #子配置文件

[root@nginx ~]# nginx -s reload
​
#查看系统打开文件的数量是多少
[root@nginx ~]# ulimit -a
#修改系统打开的文件数量
[root@nginx ~]# vim /etc/security/limits.conf
nginx            -        nofile          100000
# 再次查看系统打开文件的数量是多少
[root@nginx ~]# sudo -u nginx ulimit -a

2.3.2新建web站点

[root@nginx ~]# mkdir -p /usr/local/nginx/conf.d
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
}
[root@nginx ~]# mkdir -p /data/web/html
[root@nginx ~]# echo www.alan.org > /data/web/html/index.html
[root@nginx ~]# 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
[root@nginx ~]# nginx -s reload


查看错误日志

[root@nginx ~]# tail -f /usr/local/nginx/logs/error.log 

root:

指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location3.2

[root@nginx ~]# mkdir /data/web/test1 -p
​
#当访问/test1的时候 转到访问 /detaweb/test1
[root@nginx ~]# vi /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
    location /test1/ {
        root /data/web;
    }
}
[root@nginx ~]# echo /data/web/test1 > /data/web/test1/index.html
[root@nginx ~]# 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
[root@nginx ~]# nginx -s reload

alias:

定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于location上下文,此指令使用较少

[root@nginx ~]# cat /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
    location /test1/ {
        root /data/web;
    }
    location /test2 {
        alias /data/web/test1;
    }
}
[root@nginx ~]# 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
[root@nginx ~]# nginx -s reload

2.3.3location:

语法规则:

location [ = | ~ | ~* | ^~ ] uri { … } ​
= #只能精确指定文件,用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求 ^~ #用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头, #对uri的最左边部分做匹配检查,不区分字符大小写 ~ #用于标准uri前,表示包含正则表达式,并且区分大小写 ~* #用于标准uri前,表示包含正则表达式,并且不区分大写 不带符号 #匹配起始于此uri的所有的uri \ #用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号 ​ 新版本:1.26
#匹配目录优先级从高到低: (~* = ~)> 不带符号 > ^~ > = (=号不支持目录所以排在最后)
#匹配文件优先级从高到低:
= > (~* = ~) > 不带符号 > ^~
= 号后面只能跟文件,不能跟目录

[root@nginx ~]# mkdir /data/web{1,2}
[root@nginx ~]# mkdir /data/web{1,2}/test
[root@nginx ~]# echo web1 test > /data/web1/test/index.html
[root@nginx ~]# echo web2 test > /data/web2/test/index.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
​
    location /test {
        root /data/web1;
    }
​
    location = /test {
        root /data/web2;
    }
}[root@nginx ~]# nginx -s reload
#测试
访问http://172.25.254.100/test/
出现web1 test
#测试模糊匹配
[root@nginx ~]# mkdir -p /data/web1/{test1,tee}
[root@nginx ~]# echo test1 > /data/web1/test1/index.html
[root@nginx ~]# echo tee > /data/web1/tee/index.html
[root@nginx ~]# mkdir -p /data/web1/lee
[root@nginx ~]# echo lee > /data/web1/lee/index.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.jingwen.org;
    root /data/web/html;
    index index.html;
​
    location ^~ /t {
        root /data/web1;
    }
}[root@nginx ~]# nginx -s reload

2.3.4nginx的用户认证

# 创建默认认证文件
[root@nginx ~]#htpasswd -cm /usr/local/nginx/.htpasswd admin
redhat
[root@nginx ~]#htpasswd -m /usr/local/nginx/.htpasswd lee #有这个文件去掉c选项
redhat
​
[root@nginx ~]# mkdir /data/web/lee
[root@nginx ~]# echo lee > /data/web/lee/index.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.jingwen.org;
    root /data/web/html;
    index index.html;
​
    location /lee {
        root /data/web;
        auth_basic "login password !!";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
}
[root@nginx ~]# nginx -s reload

2.3.5自定义错误页面

[root@nginx ~]# mkdir /data/web/errorpage -p
[root@nginx ~]# echo  error page > /data/web/errorpage/40x.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    error_page 404 /40x.html;
    
    location = /40x.html {
        root /data/web/errorpage;
    }
}
[root@nginx ~]# nginx -s reload

测试

[root@node100 ~]# curl www.alan.org/testa

或者在浏览器访问www.alan.org/testa

2.3.6自定义错误日志

[root@nginx ~]# mkdir /var/log/alan.org
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    error_log /var/log/alan.org/error.log;
    access_log /var/log/alan.org/access.log;
}[root@nginx ~]# nginx -s reload

测试

[root@nginx ~]# curl www.alan.org
[root@nginx ~]# cat /var/log/alan.org/access.log
[root@nginx ~]# curl www.alan.org/aaa
[root@nginx ~]# cat /var/log/alan.org/error.log

2.3.7检测文件是否存在

[root@nginx ~]# rm -rf /data/web/html/index.html
[root@nginx ~]# rm -rf /data/web/html/error/
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    error_log /var/log/alan.org/error.log;
    access_log /var/log/alan.org/access.log;
    try_files $uri $uri.html $uri/index.html /error/default.html;}
[root@nginx ~]# nginx -s reload;

测试

[root@nginx ~]# curl www.alan.org
500[root@nginx ~]# mkdir /data/web/html/error
[root@nginx ~]# echo error default > /data/web/html/error/default.html
​
#测试
[root@nginx ~]# curl www.alan.org
error default

2.3.8长链接

[root@nginx ~]# echo www.alan.org > /data/web/html/index.html
​
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
http {
    keepalive_timeout 65;
    keepalive_requests 2;
}
[root@nginx ~]# nginx -s reload
​
# 长链接测试工具
[root@nginx ~]#dnf install telnet -y
# 测试
[root@nginx ~]#telnet www.alan.org 80
GET / HTTP/1.1
Host: www.alan.org
​
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 06:45:42 GMT
Content-Type: text/html
Content-Length: 18
Last-Modified: Fri, 16 Aug 2024 06:45:22 GMT
Connection: keep-alive
ETag: "66bef582-12"
Accept-Ranges: bytes
​

2.3.9作为下载服务器配置

#注意:download不需要index.html文件
[root@Nginx ~]# mkdir /data/web/download
[root@Nginx ~]# dd if=/dev/zero of=/data/web/download/leefile bs=1M count=100[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
​
    location /download {
        autoindex on; #自动索引功能
        autoindex_exact_size on; #计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb、mb、gb)
        autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间
        limit_rate 1024k; #限速,默认不限速 
    }
}

2.4nginx的高级配置

2.4.1nginx的状态页

[root@nginx ~]# vim /usr/local/nginx/conf.d/status.conf
server {
    listen 80;
    server_name status.alanorg;
    root /data/web/html;
    index index.html;
    
    location /status {
        stub_status;
        allow 172.25.254.1; #指定给谁看
        deny all;
        #auth_basic "login";
        #auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
}
[root@nginx ~]# nginx -s reload

测试


记得在windows做解析  172.25.254.100 status.alan.org
​
访问http://status.alan.org/status
​
Active connections: 1 
server accepts handled requests
 21 21 25 
Reading: 0 Writing: 1 Waiting: 0[root@nginx ~]# curl status.alan.org/status
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.24.0</center>
</body>
</html>

2.4.2nginx压缩

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
http {
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1k;
    gzip_http_version 1.1;
    gzip_vary on;
    gzip_types text/plain application/javascript application/x-javascript text/css
application/xml text/javascript application/x-httpd-php image/gif image/png;
}
[root@nginx ~]# nginx -s reload
​
[root@nginx ~]# echo hello alan >  /data/web/html/small.html
[root@nginx ~]# du -sh /usr/local/nginx/loges/access.log   #查看这个文件多大
[root@nginx ~]# cat /usr/local/nginx/loges/access.log > /data/web/html/big.html

测试

[root@nginx ~]# curl --head --compressed 172.25.254.100/small.html
[root@nginx ~]# curl --head --compressed 172.25.254.100/big.html

2.5Nginx Rewrite相关功能

2.5.1if判定

[root@nginx ~]# mkdir /data/web/html/test2
[root@nginx ~]# echo test2 > /data/web/html/test2/index.html
​
[root@nginx ~]# vim /location /test2 {
        if ( !-e $request_filename ){
            echo "$request_filename is not exist";
        }
    }
/local/nginx/conf.d/vars.conf
​
[root@nginx ~]# nginx -s reload
​
#测试
[root@nginx ~]# curl var.alan.org/test2/index.html 
test2

2.5.2break指令

[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
 location /break {
        default_type text/html;
        set $name alan;
        echo $name;
        if ( $http_user_agent = "curl/7.76.1" ){
            break;
        }
        set $id 666;
        echo $id;
    }
[root@nginx ~]# nginx -s reload

测试

[root@nginx ~]# curl  var.alan.org/break
alan
​
[root@nginx ~]# curl -A "firefox"  var.alan.org/break
alan
666

2.5.3return指令

[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
   location /return {
        default_type text/html;
        if ( !-e $request_filename){
            return 301 http://www.baidu.com;
        }
        echo "$request_filename is exist";
    }[root@nginx ~]# nginx -s reload

测试

#return不存在时
[root@nginx ~]# ll /data/web/html
total 24
-rw-r--r-- 1 root root 15423 Aug 16 16:16 big.html
drwxr-xr-x 2 root root    26 Aug 16 14:34 error
-rw-r--r-- 1 root root    18 Aug 18 11:04 index.html
-rw-r--r-- 1 root root    16 Aug 16 16:15 small.html
drwxr-xr-x 2 root root    24 Aug 18 11:45 test2
drwxr-xr-x 2 root root    24 Aug 18 10:41 var
[root@nginx ~]# curl -I var.alan.org/return
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 03:54:09 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.baidu.com[root@nginx ~]# mkdir  -p /data/web/html/return
[root@nginx ~]# curl -I var.alan.org/return
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 03:54:33 GMT
Content-Type: text/html
Connection: keep-alive
​
[root@nginx ~]# curl var.alan.org/return
/data/web/html/return is exist

在这里插入图片描述

2.5.4rewirte指令

利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型

  • 跳转型指由客户端浏览器重新对新地址进行请求

  • 代理型是在WEB服务器内部实现跳转

2.5.5临时和永久

准备

[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
    listen 80;
    server_name var.alae.org;
    root /data/web/html;
    index index.html;
    location / {
        root /data/web/var;
        index index.html;
        #rewrite / http://www.alan.com permanent;
        #rewrite / http://www.alan.com redirect;
    }
}
[root@nginx ~]# nginx -s reload
[root@nginx ~]# echo var page > /data/web/var/index.html
[root@nginx conf.d]# curl www.alan.org
www.alan.com
[root@nginx conf.d]# curl var.alan.org
var page

永久重定向301

[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
location / {
        root /data/web/var;
        index index.html;
        rewrite / http://www.alan.com permanent;
        #rewrite / http://www.alan.com redirect;
    }
[root@nginx ~]# nginx -s reload
​
[root@nginx conf.d]# curl -I var.alan.org
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 12:13:09 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.alan.com

临时重定向302

[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
location / {
        root /data/web/var;
        index index.html;
        #rewrite / http://www.timinglee.com permanent;
        rewrite / http://www.timinglee.com redirect;
    }
[root@nginx ~]# nginx -s reload
​
[root@nginx conf.d]# curl -I var.alan.org
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 12:13:41 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://www.alan.com

2.5.6全站加密

[root@nginx ~]# cd /usr/local/nginx/
[root@nginx nginx]# mkdir certs
[root@nginx nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/alan.org.key -x509 -days 365 -out /usr/local/nginx/certs/alan.org.crt
[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
    listen 80;
    listen 443 ssl;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/alan.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/alan.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
​
    location / {
        if ( $scheme = http ){
            rewrite /(.*) https://$host/$1 redirect;
        }
        if ( !-e $request_filename ){
            rewrite /(.*) https://$host/index.html redirect;      #如果$request_filename不存在,则触发index.html
        }
    }
}
[root@nginx ~]# nginx -s reload
[root@nginx conf.d]# curl -I alan.org
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 12:50:40 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://www.alan.org

2.5.7防盗链

#盗链的实现
[root@nginx ~]# mkdir -p /data/web/html/images
[root@nginx ~]# mv daolian.png /data/web/html
[root@nginx ~]# mv lee.png /data/web/html/images/#node1
[root@node1 ~]# dnf install httpd -y
[root@node1 ~]# cd /var/www/html
[root@node1 html]# vim index.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.alan.org/images/lee.png" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.alan.org>狂点老李</a>出门见喜</p>
</body>
</html>
# 防盗链
[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
    listen 80;
    listen 443 ssl;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/alan.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/alan.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
​
    location /images {
        valid_referers none blocked server_names *.alan.org ~/.baidu/.;
        if ( $invalid_referer ) {
            return 404;
        }
    }
}
[root@nginx ~]# nginx -s reload

2.6反向代理

2.6.1http反向代理

# node1/2配置
[root@node1 ~]# dnf install httpd -y
[root@node1 ~]# systemctl enable --now httpd
[root@node1 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@node2 ~]# systemctl enable --now httpd
[root@node2 ~]# echo 172.25.254.20 > /var/www/html/index.html
[root@node2 ~]# vim /etc/httpd/conf/httpd.conf
Listen 8080
[root@node2 ~]# systemctl restart httpd

测试

# 测试
[root@nginx ~]# curl 172.25.254.10
172.25.254.10
[root@nginx ~]# curl 172.25.254.20
172.25.254.20
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.timinglee.org;
​
    location / {
        proxy_pass http://172.25.254.10:80;
    }
​
    location /static {
        proxy_pass http://172.25.254.20:8080;
    }
}
[root@nginx ~]# nginx -s reload
​
#测试
[root@nginx ~]# curl www.alan.org
172.25.254.10
[root@nginx ~]# curl www.alan.org/static/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
(node2没有static目录)
[root@node2 ~]# mkdir -p /var/www/html/static
[root@node2 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html
​
#测试
[root@nginx ~]# curl www.alan.org
172.25.254.10
[root@nginx ~]# curl www.alan.org/static/
static 172.25.254.20

2.6.2缓存功能

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#gzip  on;    
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
location /static {
        proxy_pass http://172.25.254.20:8080;
        proxy_cache proxycache;
        proxy_cache_key $request_uri;
        proxy_cache_valid 200 302 301 10m;
        proxy_cache_valid any 1m;
    }
[root@nginx ~]# nginx -s reload
[root@node1 ~]# vim /etc/hosts

测试

[root@node1 ~]# ab -n1000 -c100 http://www.alan.org/static/index.html
Requests per second:    8908.92 [#/sec] (mean) (未做缓存)
Requests per second:    12933.77 [#/sec] (mean)

2.6.3http反向代理负载均衡

反向代理示例:后端多台web服务器

172.25.254.100 #Nginx 代理服务器
172.25.254.10 #后端web A,Apache部署
172.25.254.20 #后端web B,Apache部署
# 部署后端 Apache服务器
[root@node1 ~]# dnf install httpd -y
[root@node1 ~]# echo "172.25.254.10" > /var/www/html/index.html
[root@node1 ~]# systemctl enable --now httpd
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
upstream webcluster {
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:8080 fail_timeout=15s max_fails=3;
    server 172.25.254.100:80 backup;
}
server {
    listen 80;
    server_name www.timinglee.org;
​
    location / {
        proxy_pass http://webcluster;
    }}
[root@nginx ~]# nginx -s reload

#测试
[root@nginx ~]# curl www.alan.org
172.25.254.10
[root@nginx ~]# curl www.alan.org
172.25.254.20
# 基于Cookie 实现会话绑定
upstream webcluster {
    #ip_hash;
    #hash $request_uri consistent;
    hash $cookie_lee;
    server 172.25.254.10:80 fail_timeout=15s max_fails=3;
    server 172.25.254.20:8080 fail_timeout=15s max_fails=3;
    #server 172.25.254.100:80 backup;
}
​
​
[root@nginx ~]# curl www.alan.org
172.25.254.10
[root@nginx ~]# curl www.alan.org
172.25.254.20
[root@nginx ~]# curl -b "lee=1" www.alan.org
172.25.254.10
[root@nginx ~]# curl -b "lee=1" www.alan.org
172.25.254.10

2.6.4Nginx四层负载均衡

DNS

# 环境 node1\node2
[root@node1 ~]# dnf install bind -y
[root@node1 ~]# vim /etc/named.conf 
//      listen-on port 53 { 127.0.0.1; };
//      listen-on-v6 port 53 { ::1; };
//      allow-query     { localhost; };
​
dnssec-validation no;
[root@node1 ~]# vim /etc/named.rfc1912.zones 
zone "alan.org" IN {
        type master;
        file "alan.org.zone";
        allow-update { none; };
};[root@node1 ~]# cd /var/named
[root@node1 named]# cp named.localhost alan.org.zone -p
[root@node1 named]# vim alan.org.zone
$TTL 1D
@       IN SOA  ns.timinglee.org root.alan.org. (
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        NS      ns.alan.org.
NS      A       172.25.254.10
www     A       172.25.254.10[root@node1 named]# systemctl start named
[root@node1 named]# dig www.alan.org @172.25.254.10
[root@node1 named]# scp -p /etc/named.{conf,rfc1912.zones} root@172.25.254.20:/etc/
[root@node1 named]# scp -p /var/named/alan.org.zone root@172.25.254.20:/var/named/alan.org.zone
[root@node2 named]# chgrp named alan.org.zone 
[root@node2 named]# systemctl restart named
[root@node2 named]# dig www.alan.org @172.25.254.20
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
include "/usr/local/nginx/tcpconf.d/*.conf";
[root@nginx ~]# mkdir -p /usr/local/nginx/tcpconf.d
[root@nginx ~]# vim /usr/local/nginx/tcpconf.d/dns.conf 
stream {
    upstream dns {
        server 172.25.254.10:53 fail_timeout=15s max_fails=3;
        server 172.25.254.20:53 fail_timeout=15s max_fails=3;
    }
​
    server {
        listen 53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }
}
[root@nginx ~]# nginx -s reload

测试

​
#测试
[root@nginx ~]# dig www.alan.org @172.25.254.100; <<>> DiG 9.16.23-RH <<>> www.alan.org @172.25.254.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28013
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: b7555ae27da74d590100000066c216da67395c8bb9e26570 (good)
;; QUESTION SECTION:
;www.alan.org.     IN  A
​
;; ANSWER SECTION:
www.alan.org.  86400   IN  A   172.25.254.10[root@nginx ~]# dig www.alan.org @172.25.254.100
; <<>> DiG 9.16.23-RH <<>> www.alan.org @172.25.254.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56262
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 2a17fdf418eb234d0100000066c216e6f94e6503ec327810 (good)
;; QUESTION SECTION:
;www.alan.org.     IN  A
​
;; ANSWER SECTION:
www.alan.org.  86400   IN  A   172.25.254.20

2.6.5数据库

# node1/2
[root@node1 ~]# dnf install mariadb-server -y
[root@node1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=10
[root@node1 ~]# systemctl start mariadb.service 
# 授权
MariaDB [(none)]> CREATE USER lee@'%' identified by 'lee';
Query OK, 0 rows affected (0.002 sec)
​
MariaDB [(none)]> GRANT ALL ON *.* to lee@'%';
Query OK, 0 rows affected (0.001 sec)
[root@nginx ~]# vim /usr/local/nginx/tcpconf.d/dns.conf 
stream {
    upstream dns {
        server 172.25.254.10:53 fail_timeout=15s max_fails=3;
        server 172.25.254.20:53 fail_timeout=15s max_fails=3;
    }
    upstream mysql {
        server 172.25.254.10:3306 fail_timeout=15s max_fails=3;
        server 172.25.254.20:3306 fail_timeout=15s max_fails=3;}
​
    server {
        listen 3306;
        proxy_timeout 60s;
        proxy_pass mysql;
    }
​
    server {
        listen 53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }
}
[root@nginx ~]# nginx -s reload
[root@nginx ~]# dnf install mariadb -y #下载数据库的客户端

测试·

[root@nginx ~]# mysql -u lee -p -h 172.25.254.100
lee
MariaDB [(none)]> SELECT @@server_id
    -> ;
+-------------+
| @@server_id |
+-------------+
|          20 |
+-------------+
1 row in set (0.001 sec)
[root@nginx ~]# mysql -u lee -p -h 172.25.254.100
lee
MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|          10 |
+-------------+
1 row in set (0.002 sec)

2.6.6案例: Nginx与php-fpm在同一服务器

nginx源码安装

[root@nginx ~]# systemctl stop nginx
[root@nginx ~]# cd /usr/local/
[root@nginx local]# rm -rf /usr/local/nginx/
[root@nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz 
[root@nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz 
[root@nginx ~]# cd nginx-1.26.1/
./configure --prefix=/usr/local/nginx --add-module=/root/echo-nginx-module-0.63 --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33 --user=nginx --group=nginx --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-pcre
[root@nginx nginx-1.26.1]# systemctl start nginx
[root@nginx nginx-1.26.1]# nginx -V
[root@nginx nginx-1.26.1]# ps -aux | grep nginx
root        5493  0.0  0.0   9908   924 ?        Ss   10:43   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx       5494  0.0  0.1  13804  4708 ?        S    10:43   0:00 nginx: worker process
root        5509  0.0  0.0 221664  2252 pts/0    S+   10:44   0:00 grep --color=auto nginx
​

php源码安装

[root@nginx ~]# tar zxf php-8.3.9.tar.gz 
[root@nginx ~]# cd php-8.3.9/
[root@nginx php-8.3.9]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel
[root@nginx ~]# https://mirrors.aliyun.com/rockylinux/9.4/devel/x86_64/kickstart/Packages/o/oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm  
[root@nginx ~]# dnf install oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
[root@nginx php-8.3.9]# ./configure --prefix=/usr/local/php --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --with-curl --with-iconv --with-mhash --with-zlib --with-openssl --enable-mysqlnd --with-mysqli --with-pdo-mysql --disable-debug --enable-soap --enable-sockets --enable-xml --enable-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd
[root@nginx php-8.3.9]# ls (有makefile)
[root@nginx php-8.3.9]# make && make install

php相关配置优化

[root@Nginx ~]# cd /usr/local/php/etc
[root@nginx etc]# ls
php-fpm.conf.default  php-fpm.d
[root@Nginx etc]# cp -p php-fpm.conf.default php-fpm.conf
[root@Nginx etc]# vim php-fpm.conf
#去掉注释
pid = run/php-fpm.pid #指定pid文件存放位置
[root@Nginx etc]# cd php-fpm.d/
[root@nginx php-fpm.d]# ls
www.conf.default
[root@Nginx php-fpm.d]# cp -p www.conf.default www.conf

生成主配置文件

[root@Nginx php-fpm.d]# cd /root/php-8.3.9/
[root@Nginx php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@Nginx ~]# vim /usr/local/php/etc/php.ini
[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
date.timezone = Asia/Shanghai #修改时区

查找时区

[root@nginx ~]# timedatectl list-timezones | grep Asia/Shanghai
Asia/Shanghai

生成启动文件

[root@Nginx ~]# cd /root/php-8.3.9/sapi/fpm
[root@Nginx fpm]# cp php-fpm.service /lib/systemd/system/
[root@nginx fpm]# vim /lib/systemd/system/php-fpm.service 
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by this unit.
#ProtectSystem=full #注释该内容
[root@Nginx fpm]# systemctl daemon-reload
[root@Nginx fpm]# systemctl start php-fpm.service
[root@Nginx fpm]# netstat -antlupe | grep php
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      0          132259     158979/php-fpm: mas 

测试页面

[root@nginx ~]# mkdir -p /data/web/php
[root@nginx ~]# cd /usr/local/php/bin/
[root@nginx bin]# vim ~/.bash_
.bash_history  .bash_logout   .bash_profile  
[root@nginx bin]# vim ~/.bash_profile 
export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/php/sbin
[root@nginx bin]# source ~/.bash_profile 
[root@nginx bin]# cd /data/web/php/
[root@nginx php]# vim index.php
[root@nginx php]# cat index.php 
<?php
    phpinfo();
?>
[root@nginx conf]# cd /usr/local/nginx/
[root@nginx nginx]# mkdir conf.d
[root@nginx nginx]# vim conf/nginx.conf
include "/usr/local/nginx/conf.d/*.conf";{
[root@nginx ~]# vim /usr/local/php/etc/php-fpm.d/www.conf
listen = 127.0.0.1:9000
}
[root@nginx nginx]# vim conf.d/vhost.conf
server {
    listen 80;
    server_name www.timinglee.org;
    root /data/web/html;
    index index.html;
​
    location ~\.php$ {
        root /data/web/php;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}
[root@nginx nginx]# nginx -t
[root@nginx nginx]# nginx -s reload

php高速缓存
部署方法

[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
upstream memcache {
    server 127.0.0.1:11211;
    keepalive 512;
}
server {
    listen 80;
    server_name www.alan.org;
    root /data/web/html;
    index index.html;
    location /memc {
        internal;
        memc_connect_timeout 100ms;
        memc_send_timeout 100ms;
        memc_read_timeout 100ms;
        set $memc_key $query_string; #使用内置变量$query_string来作为key
        set $memc_exptime 300; #缓存失效时间300秒
        memc_pass memcache;
    }
    location ~ \.php$ {
        root /data/web/php;
        set $key $uri$args; #设定key的值
        srcache_fetch GET /memc $key; #检测mem中是否有要访问的php
        srcache_store PUT /memc $key; #缓存为加载的php数据
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}
[root@Nginx ~]# nginx -s reload
​
#测试
[root@nginx ~]# ab -n1000 -c10 http://www.alan.org/index.php
Failed requests:        0

2.7nginx的二次开发

编译安装openresty

[root@nginx ~]# systemctl stop nginx
[root@nginx ~]# netstate -antupe | grep nginx
[root@nginx ~]# killall -9 nginx
[root@nginx ~]# netstate -antupe | grep nginx
[root@Nginx ~]#dnf -yq install gcc pcre-devel openssl-devel perl
[root@Nginx ~]#useradd -r -s /sbin/nologin nginx
[root@Nginx ~]#cd /usr/local/src
[root@Nginx src]#wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@Nginx src]#tar xf openresty-1.17.8.2.tar.gz
[root@Nginx src]#cd openresty-1.17.8.2/
[root@Nginx openresty-1.17.8.2]#./configure \
--prefix=/apps/openresty \
--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
[root@Nginx openresty-1.17.8.2]#make && make install
[root@Nginx openresty-1.17.8.2]#ln -s /apps/openresty/bin/* /usr/bin/
[root@Nginx openresty-1.17.8.2]#openresty -v
nginx version: openresty/1.17.8.2
[root@Nginx openresty-1.17.8.2]#openresty
[root@Nginx openresty-1.17.8.2]#ps -ef |grep nginx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破晓⁠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值