全网最全面的Nginx内容(理论与实践相结合)

目录

一、Web服​​务

1.1 web服务访问流程

1.2 Web服务

1.2.1 Web服务器分类

1.2.2 Apache经典的Web服务器

1.2.2.1 Apache介绍

1.2.2.2 Apache三种工作模式

1.2.3 Nginx——高性能web服务

1.2.4 apache和nginx对比

Nginx

Apache

1.2.5 正向代理与反向代理

三、nginx安装

3.1 安装

3.2 nginx开机自启

3.3 平滑升级

3.4 回滚 

3.6 nginx全局配置

3.7 创建PC web站点

3.8 location用法

3.9 用户认证 

3.10 自定义错误页面

3.11 自定义错误日志

3.12 文件检测

3.13 长链接控制

3.14 下载服务器

四、高级设置

4.1 状态页

4.2 压缩

4.3 nginx变量

4.3.1 内置变量

4.3.2 自定义变量

五、rewrite

5.1 if、break、return

5.2 rewrite

5.3 break和last

5.4 全站加密

5.5 防盗链

六、反向代理

6.1 反向代理

6.1.1动静分离

6.1.2 缓存

6.2 实现Nginx四层负载

6.2.1 http反向代理

6.2.1.1 基础

6.2.1.2 uri哈希

6.2.1.3 cookie值哈希

6.2.2 tcp负载均衡

6.3 FastCGI​编辑

6.3.1 CGI的由来

6.3.2 为什么会有FastCGI?

6.3.3 什么是PHP-FPM?

6.3.4 Nginx源码安装

6.3.5 PHP源码安装

6.3.6 nginx反向代理负载均衡

6.3.7 PHP动态扩展模块(PHP的缓存模块)

七、nignx二次开发

7.1 openresty

7.2 编译安装openresty


一、Web服​​务

1.1 web服务访问流程

1.2 Web服务

1.2.1 Web服务器分类

Web服务分为Apache和Nginx

1.2.2 Apache经典的Web服务器

1.2.2.1 Apache介绍
  • Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行。
  • Apache是世界使用排名第一的Web服务器软件,它可以运行在几乎所有广泛使用的计算机平台上。
  • 由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一,也叫网页服务器软件 。
  • 它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。
1.2.2.2 Apache三种工作模式

Apache一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式。分别是Prefork、Worker、Event

1.Prefork MPM

Prefork MPM实现了一个非线程的、预派生的web服务器。它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。

优点:稳定

缺点: 每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景

2.Worker MPM

和prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比prefork有更多可用的线程,表现会更优秀一些;另外,如果一个线程出现了问题也会导致同一进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部。由于用到多进程多线程,需要考虑到线程的安全了,在使用keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放(该问题在prefork模式下也存在)。

优点:相比prefork占用的内存较少,可以同时处理更多的请求

缺点:使用keepalive的长链接方式,某个线程会一直占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在prefork模式下,同样会发生)

3.event MPM

Apache 中最新的模式, 2012 年发布的 apache 2.4.X 系列正式支持 event 模型 , 属于事件驱动模型 (epoll) 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式。

这是Apache最新的工作模式,它和worker模式很像,不同的是在于它解决了keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。

优点: 单线程响应请求多,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当真是请求的时候,将请求传递给服务线程,执行完毕后,有允许它释放

缺点:没有线程安全控制

1.2.3 Nginx——高性能web服务

1.什么是nginx?
NGINX 是一个开源的 Web 服务器和反向代理服务器,它使用 Nginx 作为 Web 服务器和反向代理服务器的原因是它拥有高性能、可扩展性和可靠性。它可以处理大量的并发连接,并且可以缓存 HTTP 请求以提高性能。

2.工作原理
NGINX是由俄罗斯一名程序员开发,于2020年12月15日正式发布公开版本,其工作原理是将 HTTP 请求转发到服务器,然后将响应返回给用户。它可以通过配置来支持缓存、SSL 终止、负载均衡等功能。NGINX 可以运行在多种操作系统上,如 Linux、Windows 等。
3.Nginx功能

  • 负载均衡:NGINX 可以通过轮询、加权轮询、最小连接数等方法对传入的请求进行负载均衡。
  • 缓存:NGINX 可以缓存 HTTP 请求以提高性能,可以使用 Etag、If-None-Match 等指令来缓存请求。
  • SSL 终止:NGINX 可以终止 HTTPS 请求并将其转换为 HTTP 请求,以便可以将其传递给 Web 服务器。
  • 反向代理:NGINX 可以充当 Web 服务器和客户端之间的代理,将请求转发到服务器,并将响应返回给客户端。
  • 路由:NGINX 可以根据 URL 将请求转发到不同的服务器,也可以根据请求的参数、状态码等来路由请求。

1.2.4 apache和nginx对比

Nginx

  • 轻量级,采用 C 进行编写,同样的 web 服务,会占用更少的内存及资源
  • 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apache 高很多,而 apache 则是阻塞型的。在高并发下 nginx 能保持低资源低消耗高性能 ,而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。
  • nginx 处理静态文件好,静态处理性能比 apache 高三倍以上
  • nginx 的设计高度模块化,编写模块相对简单
  • nginx 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂 ,重启的时候发现配置出错了,会很崩溃
  • nginx 作为负载均衡服务器,支持 7 层负载均衡
  • nginx 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器
  • 启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,还能够不间断服务的情况下进行软件版本的升级
  • 社区活跃,各种高性能模块出品迅速

Apache

  • apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
  • apache 发展到现在,模块超多,基本想到的都可以找到
  • apache 更为成熟,少 bug ,nginx 的 bug 相对较多
  • apache 超稳定
  • apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
  • apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
  • apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区

1.2.5 正向代理与反向代理

正向代理

正向代理(forward proxy):是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。

正向代理,其实是"代理服务器"代理了"客户端",去和"目标服务器"进行交互。

反向代理

 反向代理(reverse proxy):是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

反向代理,其实是"代理服务器"代理了"目标服务器",去和"客户端"进行交互。

例如,有时候,用户想要访问某国外网站,该网站无法在国内直接访问,但是我们可以访问到一个代理服务器,这个代理服务器可以访问到这个国外网站。这样呢,用户对该国外网站的访问就需要通过代理服务器来转发请求,并且该代理服务器也会将请求的响应再返回给用户。这个上网的过程就是用到了正向代理。 

二、IO模型

三、nginx安装

3.1 安装

1.下载软件包

官方源码包下载地址

wget https://nginx.org/download/nginx-1.26.1.tar.gz

获取到安装包

[root@nginx-node1 ~]# wget https://nginx.org/en/download.html/nginx-1.24.0.tar.gz

解压安装包

[root@nginx-node1 ~]# tar -xzvf nginx-1.24.0.tar.gz 

安装源码编译与nginx依赖的库 

[root@nginx-node1 ~]# dnf install -y gcc pcre-devel zlib-devel openssl-devel

配置/检测

[root@nginx-node1 ~]# cd nginx-1.24.0
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module

# 生成了Makefile和objs
[root@nginx-node1 nginx-1.24.0]# ls
auto     CHANGES.ru  configure  html     Makefile  objs    src
CHANGES  conf        contrib    LICENSE  man       README

编译

[root@nginx-node1 nginx-1.24.0]# make

安装

生成相关的软件存放目录和配置文件

[root@nginx-node1 nginx-1.24.0]# make install
# 在make install之前,没有该文件
[root@nginx-node1 nginx-1.24.0]# ls /usr/local/nginx/
conf  html  logs  sbin

 将启动文件,复制到工作目录下的启动文件夹下

[root@nginx-node1 objs]# \cp -f nginx /usr/local/nginx/sbin/
[root@nginx-node1 objs]# ls /usr/local/nginx/sbin/
nginx

创建用户

[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
[root@nginx-node1 ~]# id nginx
uid=1001(nginx) gid=1001(nginx) groups=1001(nginx)

 启动nginx

[root@nginx-node1 ~]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ./nginx
[root@nginx-node1 sbin]# ps aux | grep nginx
root       40234  0.0  0.0   9836   928 ?        Ss   23:38   0:00 nginx: master process nginx
nginx      40235  0.0  0.1  13696  4792 ?        S    23:38   0:00 nginx: worker process
root       40237  0.0  0.0 221668  2424 pts/2    S+   23:38   0:00 grep --color=auto nginx

[root@nginx-node1 sbin]# nginx -s stop
[root@nginx-node1 sbin]# ps aux | grep nginx
root       40248  0.0  0.0 221668  2320 pts/2    S+   23:52   0:00 grep --color=auto nginx

设置环境变量,可以直接使用nginx

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

3.2 nginx开机自启

[root@nginx-node1 ~]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[root@nginx-node1 ~]# systemctl daemon-reload
# 就可以使用systemctl命令了
[root@nginx-node1 ~]# systemctl restart nginx

3.3 平滑升级

1.下载源码包

[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.26.1.tar.gz

2.解压

[root@nginx-node1 ~]# tar -xzvf nginx-1.26.1.tar.gz 
[root@nginx-node1 ~]# tar -xzvf echo-nginx-module-0.63.tar.gz 

 3.配置/检测

[root@nginx-node1 ~]# cd nginx-1.26.1
# 添加了echo-nginx-module-0.63模块
[root@nginx-node1 nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module  --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --add-module=/root/echo-nginx-module-0.63

 4.编译

[root@nginx-node1 nginx-1.26.1]# make
# 不需要再make install,刚刚已经安装过了

5.将老的nginx替换成新的nginx

[root@nginx-node1 nginx-1.26.1]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# cp nginx nginx.old
[root@nginx-node1 sbin]# cd /root/nginx-1.26.1/objs/
# -f 强制覆盖
[root@nginx-node1 objs]# \cp -f nginx /usr/local/nginx/sbin/

6.

[root@nginx-node1 sbin]# ps aux | grep nginx
root       47359  0.0  0.0   9864   932 ?        Ss   16:30   0:00 nginx: master process nginx
nginx      47360  0.0  0.1  13736  4820 ?        S    16:30   0:00 nginx: worker process
root       47362  0.0  0.0 221668  2260 pts/1    S+   16:30   0:00 grep --color=auto nginx

[root@nginx-node1 ~]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 16:19:37 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Fri, 16 Aug 2024 15:19:47 GMT
Connection: keep-alive
ETag: "66bf6e13-267"
Accept-Ranges: bytes

启用新的进程 

[root@nginx-node1 sbin]# kill -USR2 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root       47359  0.0  0.0   9864  2648 ?        Ss   16:30   0:00 nginx: master process nginx
nginx      47360  0.0  0.1  13736  4820 ?        S    16:30   0:00 nginx: worker process
root       47363  0.0  0.1   9864  6112 ?        S    16:30   0:00 nginx: master process nginx
nginx      47364  0.0  0.1  13724  4812 ?        S    16:30   0:00 nginx: worker process
root       47366  0.0  0.0 221668  2272 pts/1    S+   16:30   0:00 grep --color=auto nginx

停止老进程 

[root@nginx-node1 sbin]# kill -WINCH 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root       47359  0.0  0.0   9864  2648 ?        Ss   16:30   0:00 nginx: master process nginx
root       47363  0.0  0.1   9864  6480 ?        S    16:30   0:00 nginx: master process nginx
nginx      47372  0.0  0.1  13756  4840 ?        S    16:37   0:00 nginx: worker process
root       47382  0.0  0.0 221668  2272 pts/1    S+   16:46   0:00 grep --color=auto nginx

如果版本升级后,没有任何问题,需要关闭老的master进程的话,就可以使用

[root@nginx-node1 sbin]# kill -9 47359

 查看版本号

[root@nginx-node1 sbin]# nginx -v
nginx version: nginx/1.26.1

3.4 回滚 

[root@nginx-node1 sbin]# kill -HUP 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root       47359  0.0  0.0   9864  2648 ?        Ss   16:30   0:00 nginx: master process nginx
root       47363  0.0  0.1   9864  6480 ?        S    16:30   0:00 nginx: master process nginx
nginx      47372  0.0  0.1  13756  5308 ?        S    16:37   0:00 nginx: worker process
nginx      47400  0.0  0.1  13736  4824 ?        S    16:58   0:00 nginx: worker process
root       47402  0.0  0.0 221668  2264 pts/1    S+   16:58   0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -WINCH 47363
[root@nginx-node1 sbin]# ps aux | grep nginx
root       47359  0.0  0.0   9864  2648 ?        Ss   16:30   0:00 nginx: master process nginx
root       47363  0.0  0.1   9864  6480 ?        S    16:30   0:00 nginx: master process nginx
nginx      47400  0.0  0.1  13736  4824 ?        S    16:58   0:00 nginx: worker process
root       47417  0.0  0.0 221668  2424 pts/1    S+   17:02   0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# mv nginx nginx.new
[root@nginx-node1 sbin]# mv nginx.old nginx
[root@nginx-node1 sbin]# ls
nginx  nginx.new
[root@nginx-node1 sbin]# nginx -v
nginx version: nginx/1.24.0

3.6 nginx全局配置

[root@nginx-node1 ~]# nginx -s stop
[root@nginx-node1 ~]# ps aux | grep nginx
root       47780  0.0  0.0 221668  2324 pts/1    S+   18:12   0:00 grep --color=auto nginx
[root@nginx-node1 ~]# nginx -g "worker_processes  5;"
[root@nginx-node1 ~]# ps aux | grep nginx
root       47783  0.0  0.0   9836   924 ?        Ss   18:12   0:00 nginx: master process nginx -g worker_processes  5;
nginx      47784  4.5  1.2  54680 45720 ?        S    18:12   0:00 nginx: worker process
nginx      47785  2.5  1.2  54680 45780 ?        S    18:12   0:00 nginx: worker process
nginx      47786  0.0  1.2  54680 45692 ?        S    18:12   0:00 nginx: worker process
nginx      47787 20.0  1.2  54680 45776 ?        S    18:12   0:00 nginx: worker process
nginx      47788 21.0  1.2  54680 45800 ?        S    18:12   0:00 nginx: worker process
root       47790  0.0  0.0 221668  2272 pts/1    S+   18:13   0:00 grep --color=auto nginx

nginx高并发测试

Linux并发测试工具

[root@nginx-node1 ~]# yum install -y http-tools

#例如
ab -n 请求次数 -c 并发数 访问地址

ab -n 1000 -c 100 https://www.baidu.com/  表请求1000次中有100并发

[root@nginx-node1 ~]# vim /etc/security/limits.conf 
nginx   -       nofile      100000
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
events {
    worker_connections  100000;
    use epoll;
}

[root@nginx-node1 ~]# sudo -u nginx ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 14546
max locked memory           (kbytes, -l) 64
max memory size             (kbytes, -m) unlimited
open files                          (-n) 100000
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 14546
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited
[root@nginx-node1 ~]# ab -c 10000 -n 10000 http://172.25.254.100/index.html

3.7 创建PC web站点

[root@nginx-node1 ~]# mkdir /usr/local/nginx/conf.d
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf

http {
    include "/usr/local/nginx/conf.d/*.conf";

}
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
}
[root@nginx-node1 ~]# mkdir -p /data/web/html
[root@nginx-node1 ~]# echo www.lm.org > /data/web/html/index.html
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100    www.lm.org 
[root@nginx-node1 ~]# curl www.lm.org
www.lm.org

3.8 location用法

=         #用于标准 uri 前,需要请求字串与 uri 精确匹配,大小敏感 , 如果匹配成功就停止向下匹配并立
即处理请求
^~         #用于标准 uri 前,表示包含正则表达式 , 并且匹配以指定的正则表达式开头
            #对 uri 的最左边部分做匹配检查,不区分字符大小写
~         #用于标准 uri 前,表示包含正则表达式 , 并且区分大小写
~*         #用于标准 uri 前,表示包含正则表达式 , 并且不区分大写不带符号 # 匹配起始于此 uri 的所有的 uri
\         #用于标准 uri 前,表示包含正则表达式并且转义字符。可以将 . * ? 等转义为普通符号
对目录匹配优先级:(~* = ~)> 不带符号 > ^~ > =
对文件匹配优先级:= > (~* = ~) > 不带符号 > ^~

3.9 用户认证 

[root@nginx-node1 ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password: 
Re-type new password: 
Adding password for user admin
[root@nginx-node1 ~]# htpasswd -m /usr/local/nginx/.htpasswd lm
New password: 
Re-type new password: 
Adding password for user lm
[root@nginx-node1 ~]# cat /usr/local/nginx/.htpasswd 
admin:$apr1$yujc3BhF$8olV5TU375/3yXNV4Jfbf0
lm:$apr1$DB.oxbHz$NdHo3q5q7Gtiw4FwxKUXw1
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    location /lm {
        root /data/web;
        auth_basic "login password!";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
}
[root@nginx-node1 ~]# systemctl restart nginx

3.10 自定义错误页面

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    error_page 404 /40x.html;
    location /lm {
        root /data/web;
        auth_basic "login password!";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
    location = /40x.html {
        root /data/web/errorpage;
    }
} 
[root@nginx-node1 ~]# mkdir -p /data/web/errorpage
[root@nginx-node1 ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx-node1 ~]# systemctl restart nginx.service 

测试 

3.11 自定义错误日志

[root@nginx-node1 ~]# mkdir -p /var/log/lm.org
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    error_page 404 /40x.html;
    # 自定义错误日志
    error_log /var/log/lm.org/error.log;
    access_log /var/log/lm.org/access.log;
    location /lm {
        root /data/web;
        auth_basic "login password!";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
    location = /40x.html {
        root /data/web/errorpage;
    }
}
[root@nginx-node1 ~]# systemctl restart nginx
# 自动生成文件
[root@nginx-node1 ~]# cat /var/log/lm.org/error.log 
[root@nginx-node1 ~]# cat /var/log/lm.org/access.log 

3.12 文件检测

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    error_page 404 /40x.html;
    error_log /var/log/lm.org/error.log;
    access_log /var/log/lm.org/access.log;
    # 检测文件
    try_files $uri $uri.html $uri/index.html /erro/default.html;
    location /lm {
        root /data/web;
        auth_basic "login password!";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
    location = /40x.html {
        root /data/web/errorpage;
    }
}
[root@nginx-node1 ~]# mkdir -p /data/web/html/error
[root@nginx-node1 ~]# echo error default > /data/web/html/error/default.html

3.13 长链接控制

下载长链接测试工具

[root@nginx-node1 ~]# yum install -y telnet
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
    # 在一次长连接上所允许请求的资源的最大数量
    keepalive_requests 2;
    keepalive_timeout  65 60;
# 开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断
开,第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时
间
}
[root@nginx-node1 ~]# telnet www.lm.org 80
Trying 172.25.254.100...
Connected to www.lm.org.
Escape character is '^]'.
GET / HTTP/1.1
HOST:www.lm.org
# 回车

3.14 下载服务器

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    error_page 404 /40x.html;
    error_log /var/log/lm.org/error.log;
    access_log /var/log/lm.org/access.log;
    try_files $uri $uri.html $uri/index.html /error/default.html;
    location /lm {
        root /data/web;
        auth_basic "login password !";
        auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }
    location = /40x.html {
        root /data/web/errorpage;
    }
    location /download {
        root /data/web;
        # 自动文件索引功能
        autoindex on;
        # 打开本地时间
        autoindex_localtime on;
        # 改变存储的的那欸
        autoindex_exact_size off;
        # 限制下载速度
        limit_rate 1024k;
    }
}

四、高级设置

4.1 状态页

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/status.conf 
server {
    listen 80;
    server_name status.lm.org;
    root /data/web/html;
    index index.html;
    location /status {
        stub_status;
        allow 172.25.254.1;
        deny all;
    }
}
[root@nginx-node1 ~]# systemctl restart nginx

4.2 压缩

[root@nginx-node1 ~]# 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;
    include "/usr/local/nginx/conf.d/*.conf";
    server {.....}

}
[root@nginx-node1 ~]# systemctl restart ngixn
[root@nginx-node1 ~]# du -sh /usr/local/nginx/logs/access.log 
4.1M	/usr/local/nginx/logs/access.log
[root@nginx-node1 ~]# cat /usr/local/nginx/logs/error.log > /data/web/html/small.html
[root@nginx-node1 ~]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html

4.3 nginx变量

4.3.1 内置变量

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
    listen 80;
    server_name var.lm.org;
    root /data/web/html;
    index index.html;
    location /var {
        echo $remote_addr;
        echo $args;
        echo $is_args;
        echo $document_root;
        echo $document_uri;
        echo $host;
        echo $remote_port;
        echo $remote_user;
        echo $request_method;
        echo $request_filename;
        echo $request_uri;
        echo $scheme;
        echo $server_protocol;
        echo $server_addr;
        echo $server_name;
        echo $server_port;
        echo $http_user_agent;
        echo $http_cookie;
        echo $cookie_key2;
    }
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 var.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
# -b设置cookie值,-u指定用户
[root@nginx-node1 ~]# curl -b "key1=lm,key2=lm1" -u lm:redhat var.lm.org/var?name=lm&&id=6666
172.25.254.100
name=lm
?
/data/web/html
/var
var.lm.org
44136
lm
GET
/data/web/html/var
/var?name=lm
http
HTTP/1.1
172.25.254.100
var.lm.org
80
curl/7.76.1
key1=lm,key2=lm1
lm1

4.3.2 自定义变量

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/set-var.conf
server {
    listen 80;
    server_name set.lm.org;
    root /data/web/html;
    index index.html;

    location /var {
        default_type text/html;
        set $lm lm;
        echo $lm;
    }
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 set.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# curl set.lm.org/var
lm

五、

if

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/if.conf 
server {
    listen 80;
    server_name if.lm.org;
    root /data/web/html;
    index index.html;
    location /test2 {
        if ( !-e $request_filename ) {
            echo "$request_filename is noe exist";
        }
    }
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 if.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# curl if.lm.org/test2/
/data/web/html/test2/ is noe exist

五、rewrite

5.1 if、break、return

server {
    listen 80;
    server_name if.lm.org;
    root /data/web/html;
    index index.html;
    location /test2 {
        # 当前请求的资源文件的磁盘路径不存在
        if ( !-e $request_filename ) {
            echo "$request_filename is not exist";
        }
    }
    location /break {
        default_type text/html;
        set $name lm;
        echo $name;
        if ( $http_user_agent = "curl/7.76.1" ) {
            break;
        }
        set $id 666;
        echo $id;
    }
    location /return {
        default_type text/html;
        if ( !-e $request_filename ) {
            return 301 https://www.baidu.com;
        }
        echo "$request_filename is exist";
    }

}

5.2 rewrite

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/if.conf 
server {
    listen 80;
    server_name if.lm.org;
    root /data/web/html;
    index index.html;

    location / {
        root /data/web/var;
        index index.html;
        # 永久重定向301
        rewrite / http://www.lm.com permanent;
         # 临时重定向302
        #rewrite / http://www.lm.com redirect;
    }

}

[root@nginx-node1 ~]# systemctl restart nginx

永久

临时

5.3 break和last

[root@nginx-node1 ~]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx-node1 ~]# echo test1 > /data/web/html/test1/index.html
[root@nginx-node1 ~]# echo test2 > /data/web/html/test2/index.html
[root@nginx-node1 ~]# echo last > /data/web/html/last/index.html
[root@nginx-node1 ~]# echo break > /data/web/html/break/index.html

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf 
server {
    listen 80;
    server_name var.lm.org;
    root /data/web/html;
    index index.html;
    location /break {
        rewrite ^/break/(.*) /test1/$1;
        rewrite ^/test1/(.*) /test2/$1;
    }
    location /last {
        rewrite ^/last/(.*) /test1/$1;
        rewrite ^/test1/(.*) /test2/$1;
    }
    location /test1 {
        default_type text/html;
        return 666 "ahahahahahahahah";
    }
    location /test2 {
        root /data/web/html;
    }
}
[root@nginx-node1 ~]# systemctl restart nginx

 

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf 
server {
    listen 80;
    server_name var.lm.org;
    root /data/web/html;
    index index.html;
    location /break {
        rewrite ^/break/(.*) /test1/$1 break;
        rewrite ^/test1/(.*) /test2/$1;
    }
    location /last {
        rewrite ^/last/(.*) /test1/$1 last;
        rewrite ^/test1/(.*) /test2/$1;
    }
    location /test1 {
        default_type text/html;
        return 666 "ahahahahahahahah";
    }
    location /test2 {
        root /data/web/html;
    }
}
[root@nginx-node1 ~]# systemctl restart nginx

5.4 全站加密

[root@nginx-node1 ~]# cd /usr/local/nginx/
[root@nginx-node1 nginx]# ls
client_body_temp  conf.d        html  proxy_temp  scgi_temp
conf              fastcgi_temp  logs  sbin        uwsgi_temp
[root@nginx-node1 nginx]# mkdir certs
[root@nginx-node1 nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/lm.org.key -x509 -days 365 -out /usr/local/nginx/certs/lm.org.crt
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    listen 443 ssl;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/lm.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    location / {
        # 当使用http时,强制访问https
        if ( $scheme = http ){
            rewrite /(.*) https://$host/$1 redirect;
        }
        # 判断文件是否存在
        if ( !-e $request_filename ) {
            rewrite /(.*) https://$host/index.html redirect;
        }
    }
}
[root@nginx-node1 ~]# systemctl restart nginx;

5.5 防盗链

盗链

server {
    listen 80;
    listen 443 ssl;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/lm.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    location /images {
        root /data/web/html;
    }
}

防盗 

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    listen 443 ssl;
    server_name www.lm.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/lm.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    # 全站防盗链
    #location / {
    #   valid_referers none blocked server_names *.lm.org ~/.baidu/. ;
    #   if ( $invalid_referer ) {
    #       return 404;
    #   }
    #}
    location /images {
        valid_referers none blocked server_names *.lm.org ~/.baidu/. ;
        if ( $invalid_referer ) {
            rewrite ^/ http://www.lm.org/t2.JPG;
        }
    }
}
[root@nginx-node1 ~]# systemctl restart nginx

六、反向代理

6.1 反向代理

6.1.1动静分离

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;

    location ~ \.php$ {
        proxy_pass http://172.25.254.10:80;
    }

    location /static {
        proxy_pass http://172.25.254.20:8080;
    }
}
[root@nginx-node1 ~]# systemctl restart nginx
[root@web10 ~]# yum install -y httpd
[root@web10 ~]# dnf install -y php
[root@web10 ~]# systemctl start httpd
[root@web10 ~]# vim /var/www/html/index.php
<?php
phpinfo();
?>
[root@web10 ~]# systemctl restart httpd
[root@web20 ~]# yum install -y httpd
[root@web20 ~]# systemctl start httpd
[root@web20 ~]# mkdir -p /var/www/html/static
[root@web20 ~]# echo 172.25.254.20 > /var/www/html/index.html
[root@web20 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html
[root@web20 ~]# vim /etc/httpd/conf/httpd.conf
[root@web20 ~]# systemctl restart httpd

测试

6.1.2 缓存

压测:

[root@nginx-node1 ~]# ab -n1000 -c100 http://www.lm.org/static/index.html

缓存 

[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;

[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name www.lm.org;

    location ~ \.php$ {
        proxy_pass http://172.25.254.10:80;
    }

    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-node1 ~]# systemctl restart nginx

压测: 

[root@nginx-node1 ~]# ab -n1000 -c100 http://www.lm.org/static/index.html

6.2 实现Nginx四层负载

udp 主要用于DNS的域名解析,其配置方式和指令和 http 代理类似,其基于 ngx_stream_proxy_module  模块实现 tcp 负载,另外基于模块ngx_stream_upstream_module 实现后端服务器分组转发、权重分配、状态监测、 调度算法等高级功能。

6.2.1 http反向代理

本实验先关闭缓存
6.2.1.1 基础
[root@nginx-node1 ~]# 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.lm.org;

    location / {
        proxy_pass http://webcluster;
    }
}

[root@nginx-node1 ~]# systemctl restart nginx

测试

原因:nat模式

6.2.1.2 uri哈希

6.2.1.3 cookie值哈希

6.2.2 四层负载均衡

6.2.2.1 upd负载均衡:DNS

web10与web20配置DNS服务

[root@web10 ~]# yum install -y bind

 

[root@web10 named]# cp named.localhost lm.org.zone -p

20主机 

[root@web20 ~]# yum install -y bind

 nginx主机

[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx-node1 ~]# mkdir -p /usr/local/nginx/tcpconf.d
[root@nginx-node1 ~]# systemctl restart nginx

[root@nginx-node1 ~]# 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-node1 ~]# systemctl restart nginx

6.2.2.2 tcp负载均衡:MySQL
[root@web10 ~]# yum install -y mariadb-server

 

 

[root@web20 ~]# yum install -y mariadb-server

 

 

 

 

nginx主机

[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf 
[root@nginx-node1 ~]# systemctl restart nginx

 

[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# yum install -y mariadb

 

6.3 FastCGI

6.3.1 CGI的由来

最早的 Web 服务器只能简单地响应浏览器发来的 HTTP 请求,并将存储在服务器上的 HTML 文件返回给浏 览器,也就是静态html 文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技 术,比如像php(1995 ) java(1995) python(1991) 语言开发的网站,但是 nginx/apache 服务器并不能直接运行 php java 这样的文件, apache 实现的方式是打补丁,但是 nginx 缺通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx 并回收进程,最后 nginx 在返回给客户端,那这个约定就是通用网关接口(common gateway interface ,简称 CGI) CGI (协议) 是 web 服务器和外部应用程序之间的接口标准,是cgi 程序和 web 服务器之间传递信息的标准化接口。

6.3.2 为什么会有FastCGI

CGI 协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server每收到一个请求都会创建一个CGI 进程, PHP 解析器都会解析 php.ini 文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI 进程都会执行这些操作,所以效率很低,而 FastCGI 是用来提高 CGI 性 能的,FastCGI 每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请 求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。

6.3.3 什么是PHP-FPM

PHP-FPM(FastCGI Process Manager
  • FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
  • 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server
  • 的请求
  • worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。

6.3.4 Nginx源码安装

1.下载源码包

[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.26.1.tar.gz

2.解压源码包

[root@nginx-node1 ~]# tar xzvf nginx-1.26.1.tar.gz

3.获取模块

解压命令

[root@nginx-node1 ~]# tar xvzf echo-nginx-module-0.63.tar.gz 
[root@nginx-node1 ~]# tar xvf memc-nginx-module-0.20.tar.gz 
[root@nginx-node1 ~]# tar xvf srcache-nginx-module-0.33.tar.gz 

4.下载nginx需要的依赖

[root@nginx-node1 ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y

3.检测/配置

[root@nginx-node1 ~]# cd nginx-1.26.1/
[root@nginx-node1 nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module  --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --add-module=/root/echo-nginx-module-0.63 --add-module=/root/srcache-nginx-module-0.33 --add-module=/root/memc-nginx-module-0.20 

4.编译和安装

[root@nginx-node1 nginx-1.26.1]# make && make install

5.启动

[root@nginx-node1 ~]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ls
nginx
[root@nginx-node1 sbin]# ./nginx

6.写入环境变量

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

7.创建用户

[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx

6.3.5 PHP源码安装

 1.获取onigurma

[root@nginx-node1 ~]# wget 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-node1 ~]# yum install -y oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm

2.下载其他依赖

[root@nginx-node1 ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel 

3.解压需要的模块

4.解压PHP源码包 

5.检测/配置

[root@nginx-node1 ~]# cd php-8.3.9/
[root@nginx-node1 php-8.3.9]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --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-sockets --enable-soap --enable-xml --enable-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd

6.编译和配置

[root@nginx-node1 php-8.3.9]# make && make install

 7.php相关配置优化

(1)

(2)生成子配置文件

(3)

(4)生成启动文件

(5)设置环境变量

6.3.6 nginx反向代理负载均衡

测试:

6.3.7 PHP动态扩展模块(PHP的缓存模块)

目的:解决PHP性能差问题

1.安装memcache模块

[root@nginx-node1 ~]# tar xvf memcache-8.2
[root@nginx-node1 ~]# cd memcache-8.2/
[root@nginx-node1 memcache-8.2]# yum install -y autoconf
[root@nginx-node1 memcache-8.2]# phpize
Configuring for:
PHP Api Version:         20230831
Zend Module Api No:      20230831
Zend Extension Api No:   420230831
[root@nginx-node1 memcache-8.2]# ./configure && make && make install

2.复制测试文件到nginx发布目录

3.配置php加载memcache模块 

[root@nginx-node1 ~]# vim /usr/local/php/etc/php.ini 

[root@nginx-node1 ~]# systemctl reload php-fpm

4.部署memcached

测试

[root@nginx-node1 ~]# ab -n500 -c10 http://www.lm.org/example.php

七、nignx二次开发

7.1 openresty

OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,由中国人章亦春发起,提供了很多高质量的第三方模块。

OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。

360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度用户。

7.2 编译安装openresty

[root@nginx-node1 ~]# wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@nginx-node1 ~]# tar xzvf openresty-1.25.3.1.tar.gz 
[root@nginx-node1 ~]# dnf install -y gcc pcre-devel openssl-devel perl
[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
# 检测/配置
[root@nginx-node1 ~]# cd openresty-1.25.3.1/
[root@nginx-node1 openresty-1.25.3.1]# ./configure --user=nginx --group=nginx --prefix=/usr/local/openresty --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream --without-pcre2 --with-stream_ssl_preread_module --with-http_realip_module 
[root@nginx-node1 openresty-1.25.3.1]# gmake && gmake install

 

添加环境变量

[root@nginx-node1 bin]# vim ~/.bash_profile 
[root@nginx-node1 bin]# source ~/.bash_profile

测试

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值