Nginx笔记

仅为学习记录,方便回顾复习,如有侵权请联系删除!

Nginx笔记

目录

文章目录

1 Nginx的安装和部署

1、虚拟机安装

2、宝塔Linux面板安装

yum安装命令

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh

安装成功的信息:

==================================================================
Congratulations! Installed successfully!
==================================================================
外网面板地址: http://113.225.41.61:30029/4cf225e8
内网面板地址: http://192.168.31.253:30029/4cf225e8
username: r7i5k2zk
password: 23f50284
If you cannot access the panel,
release the following panel port [30029] in the security group
若无法访问面板,请检查防火墙/安全组是否有放行面板[30029]端口
==================================================================
Time consumed: 1 Minute!

如果是虚拟机的centos系统,使用内网面板地址访问。

如果是阿里云服务器的centos系统,使用外网面板地址访问。

面板卸载

/etc/init.d/bt stop && chkconfig --del bt && rm -f /etc/init.d/bt && rm -rf /www/server/panel

记得去防火墙移除端口

firewall-cmd --remove-port=xxx/tcp --permanent  #永久移除xxx端口
firewall-cmd --reload	#刷新生效
firewall-cmd --list-all	#查看防火墙放行列表

3、Nginx的安装

3.1 使用源码编译安装

用终端连接登录远程阿里云远程服务器

上传nginx-1.21.6.tar.gz包到linux目录/usr/local/myupload/

[root@iZ2ze22yzy03bpdp3jsyqiZ myupload]# tar zxvf nginx-1.21.6.tar.gz	#解压
[root@iZ2ze22yzy03bpdp3jsyqiZ myupload]# cd nginx-1.21.6	#进入刚解压出来的目录
[root@iZ2ze22yzy03bpdp3jsyqiZ nginx-1.21.6]# ll		#查看文件
total 824
drwxr-xr-x 6 1001 1001   4096 Aug  1 08:59 auto
-rw-r--r-- 1 1001 1001 316961 Jan 25  2022 CHANGES
-rw-r--r-- 1 1001 1001 484308 Jan 25  2022 CHANGES.ru
drwxr-xr-x 2 1001 1001   4096 Aug  1 08:59 conf
-rwxr-xr-x 1 1001 1001   2590 Jan 25  2022 configure
drwxr-xr-x 4 1001 1001   4096 Aug  1 08:59 contrib
drwxr-xr-x 2 1001 1001   4096 Aug  1 08:59 html
-rw-r--r-- 1 1001 1001   1397 Jan 25  2022 LICENSE
drwxr-xr-x 2 1001 1001   4096 Aug  1 08:59 man
-rw-r--r-- 1 1001 1001     49 Jan 25  2022 README
drwxr-xr-x 9 1001 1001   4096 Aug  1 08:59 src
[root@iZ2ze22yzy03bpdp3jsyqiZ nginx-1.21.6]# ./configure --prefix=/usr/local/nginx
#解释:--prefix=/usr/local/nginx 指安装路径是/usr/local/nginx,如果前面安装了宝塔Linux面板,这一步应该不会出现环境问题。
...#等待执行完毕#
[root@iZ2ze22yzy03bpdp3jsyqiZ nginx-1.21.6]# make
[root@iZ2ze22yzy03bpdp3jsyqiZ nginx-1.21.6]# make install

启动Nginx

进入安装好的目录 /usr/local/nginx/sbin/

./nginx				#启动
./nginx -s stop		#快速停止
./nginx -s quit		#优雅关闭,在退出前完成已经接受的连接请求
./nginx -s reload	#重新加载配置

安装成功的截图如下

image-20220801090920594

安装成系统服务

在如下位置创建服务脚本nginx.service

vi /usr/lib/systemd/system/nginx.service

服务脚本内容如下(注意路径要对应,这里的路径是/usr/local/nginx/sbin):

[Unit]
Description=nginx - web server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

保存退出:wq

重新加载系统服务

systemctl daemon-reload

启动服务

systemctl start nginx.service

设置开机启动

[root@iZ2ze22yzy03bpdp3jsyqiZ usr]# systemctl enable nginx.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

在阿里云服务器管理界面添加安全组80端口规则,测试访问阿里云公网ip:47.94.17.162

或者访问虚拟机内网:http://192.168.31.253/

image-20220801093634483

3.2 使用宝塔面板安装

宝塔面板安装的版本不是nginx的开源版本,作为学习,建议使用源码编译安装,熟练了再使用宝塔版的nginx。

image-20220801093854788

2 Nginx目录结构 基本原理 配置文件

1、Nginx目录结构

linux上安装递归目录列表程序tree

[root@iZ2ze22yzy03bpdp3jsyqiZ ~]# yum -y install tree

以树状格式列出nginx的目录内容

[root@iZ2ze22yzy03bpdp3jsyqiZ ~]# tree /usr/local/nginx
/usr/local/nginx
├── client_body_temp				# POST 大文件暂存目录
├── conf							# Nginx所有配置文件的目录
│   ├── fastcgi.conf				# fastcgi相关参数的配置文件
│   ├── fastcgi.conf.default		# fastcgi.conf的原始备份文件
│   ├── fastcgi_params				# fastcgi的参数文件
│   ├── fastcgi_params.default		# fastcgi_params的原始备份文件
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types					# 媒体类型
│   ├── mime.types.default
│   ├── nginx.conf					# Nginx默认的主配置文件,日常使用和修改的文件
│   ├── nginx.conf.default
│   ├── scgi_params					# scgi相关参数文件
│   ├── scgi_params.default
│   ├── uwsgi_params				# uwsgi相关参数文件
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp					# fastcgi临时数据目录
├── html							# Nginx默认站点目录
│   ├── 50x.html					# 错误页面优雅替代显示文件,例如出现502错误时会调用此页面
│   └── index.html					# 默认的首页文件
├── logs							# Nginx日志目录
│   ├── access.log					# 访问日志文件
│   ├── error.log					# 错误日志文件
│   └── nginx.pid					# pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
├── proxy_temp						# 临时目录
├── sbin							# Nginx 可执行文件目录
│   └── nginx						# Nginx 二进制可执行程序
├── scgi_temp						# 临时目录
└── uwsgi_temp						# 临时目录

9 directories, 21 files

主要的目录是conf,html,及sbin。

  • conf目录放的是核心配置文件
  • html目录放的是静态页面
    • 50x.html是发生错误展示的页面,index.html是默认的访问页面。可以在该目录下新建html,然后在浏览器中访问,例如在该目录下新建hello.html,内容是hello,然后访问:http://47.94.17.162/hello.html
  • logs文件夹用于存放日志信息
    • error.log存放出错的信息,nginx.pid存放的是当前nginx的pid。
  • sbin存放的是可执行文件,可以用 ./nginx启动nginx

2、Nginx基本运行原理

Nginx的进程是使用经典的「Master-Worker」模型,Nginx在启动后,会有一个master进程和多个worker进程。master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。worker进程主要处理基本的网络事件,多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的。

image-20220801100632380

3、Nginx基本配置文件

Nginx的默认配置文件是nginx.conf,位置:/usr/local/nginx/conf/nginx.conf。

3.1 刚安装好的nginx.conf内容

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

3.2 去掉注释的简单版

worker_processes  1; #允许进程数量,建议设置为cpu核心数或者auto自动检测,注意Windows服务器上虽然可以启动多个processes,但是实际只会用其中一个

events {
    #单个进程最大连接数(最大连接数=连接数*进程数)
    #根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。
    worker_connections  1024;
}


http {
    #文件扩展名与文件类型映射表(是conf目录下的一个文件)
    include       mime.types;
    #默认文件类型,如果mime.types预先定义的类型没匹配上,默认使用二进制流的方式传输
    default_type  application/octet-stream;

    #sendfile指令指定nginx是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度。
    sendfile        on;
    
     #长连接超时时间,单位是秒
    keepalive_timeout  65;

 #虚拟主机的配置
    server {
    #监听端口
        listen       80;
        #域名,可以有多个,用空格隔开
        server_name  localhost;

	#配置根目录以及默认页面
        location / {
            root   html;
            index  index.html index.htm;
        }

	#出错页面配置
        error_page   500 502 503 504  /50x.html;
        #/50x.html文件所在位置
        location = /50x.html {
            root   html;
        }
        
    }

}

3 Nginx虚拟主机与域名解析

虚拟主机使用特殊的软硬件技术,把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机,每一台虚拟主机都具有独立的域名,具有完整的Internet服务器(WWW、FTP、Email等)功能,虚拟主机之间完全独立,并可由用户自行管理,在外界看来,每一台虚拟主机和一台独立的主机完全一样。

域名解析就是域名到IP地址的转换过程,IP地址是网路上标识站点的数字地址,为了简单好记,采用域名来代替ip地址标识站点地址。域名的解析工作由DNS服务器完成。

1、域名、dns、ip地址的关系

1.1 域名、ip简单介绍

  • 域名是相对网站来说的,IP是相对网络来说的。当输入一个域名的时候,网页是如何做出反应的?

    输入域名---->域名解析服务器(dns)解析成ip地址—>访问IP地址—>完成访问的内容—>返回信息。

  • Internet上的计算机IP是唯一的,一个IP地址对应一个计算机。

    一台计算机上面可以有很多个服务,也就是一个ip地址对应了很多个域名,即一个计算机上有很多网站。

1.2 IP地址和DNS地址的区别

IP地址是指单个主机的唯一IP地址,而DNS服务器地址是用于域名解析的地址。

一个是私网地址,一个是公网地址。

一个作为主机的逻辑标志,一个作为域名解析服务器的访问地址。

1.3 IP地址

IP,就是Internet Protocol的缩写,是一种通信协议,我们用的因特网基本是IP网组成的。

IP地址就是因特网上的某个设备的一个编号。

IP地址一般由网络号,主机号,掩码来组成。

IP网络上有很多路由器,路由器之间转发、通信都是只认这个IP地址,类似什么哪?就好像你寄包裹,你的写上发件人地址,你的姓名,收件人地址,收件人姓名。

这个发件人地址就是你电脑的IP的网络号,你的姓名就是你的主机号。

收件人的地址就是你要访问的IP的网络号,收件人的姓名就是访问IP的主机号。

现在还有了更复杂的IPV6,还有IPV9。

1.4 DNS是什么

我们访问因特网必须知道对端的IP地址,可是我们访问网站一般只知道域名啊,怎么办?

这时候DNS就有用处了,电脑先访问DNS服务器,查找域名对应的IP,于是,你的电脑就知道要发包的IP地址了。

2、http协议

HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器(C/S)模型。HTTP是一个无状态的协议。

HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候,就成了我们常说的HTTPS。如下图所示:

image-20220801102614719

客户端与服务器的数据交互的流程:

1)首先客户机与服务器需要建立TCP连接。只要单击某个超级链接,HTTP的工作开始,下图是TCP连接流程。

image-20220801102727715

2)建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。

3)服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容,例如返回一个HTML的文本。

4)客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。

3、虚拟主机原理

虚拟主机是为了在同一台物理机器上运行多个不同的网站,提高资源利用率引入的技术。

一般的web服务器一个ip地址的80端口只能正确对应一个网站。web服务器在不使用多个ip地址和端口的情况下,如果需要支持多个相对独立的网站就需要一种机制来分辨同一个ip地址上的不同网站的请求,这就出现了主机头绑定的方法。简单的说就是,将不同的网站空间对应不同的域名,以连接请求中的域名字段来分发和应答正确的对应空间的文件执行结果。举个例子来说,一台服务器ip地址为192.168.8.101,有两个域名和对应的空间在这台服务器上,使用的都是192.168.8.101的80端口来提供服务。如果只是简单的将两个域名A和B的域名记录解析到这个ip地址,那么web服务器在收到任何请求时反馈的都会是同一个网站的信息,这显然达不到要求。接下来我们使用主机头绑定域名A和B到他们对应的空间文件夹C和D。当含有域名A的web请求信息到达192.168.8.101时,web服务器将执行它对应的空间C中的首页文件,并返回给客户端,含有域名B的web请求信息同理,web服务器将执行它对应的空间D中的首页文件,并返回给客户端,所以在使用主机头绑定功能后就不能使用ip地址访问其上的任何网站了,因为请求信息中不存在域名信息,所以会出错。

3.1 实战-监听不同域名

配置nginx.conf

vim /usr/local/nginx/conf/nginx.conf

image-20220801111938220

image-20220801112000534

添加对应目录和网页文件

/usr/local/nginx/html/www/
├── test80
│   └── index.html
└── test81
    └── index.html

配置单机域名

C:\Windows\System32\drivers\etc\hosts

#nginx测试 begin
47.94.17.162 test81.chw1113520.cn
47.94.17.162 test80.chw1113520.cn
#nginx测试 begin

使用systemctl reload nginx重新加载配置

[root@iZ2ze22yzy03bpdp3jsyqiZ conf]# systemctl reload nginx

测试访问:http://test80.chw1113520.cn/

image-20220801113509199

测试访问:http://test81.chw1113520.cn/

image-20220801113529237

如果直接访问http://47.94.17.162/会访问到第一个站点test80

3.2 实战-监听多个端口

修改nginx.conf

image-20220801142715976

image-20220801142745697

使用systemctl reload nginx重新加载配置(需要设置防火墙放行81端口,并且由于我的是阿里云服务器,再去安全组添加端口规则允许访问81端口即可)

测试访问http://47.94.17.162:80/

image-20220801145026774

测试访问http://47.94.17.162:81/

image-20220801144955351

4、泛域名

所谓 ”泛域名解析“ 是指:利用通配符 * (星号)来做次级域名以实现所有的次级域名均指向同一IP地址。

好处:

  1. 可以让域名支持无限的子域名(这也是泛域名解析最大的用途)。

  2. 防止用户错误输入导致的网站不能访问的问题

  3. 可以让直接输入网址登陆网站的用户输入简洁的网址即可访问网站

泛域名在实际使用中作用是非常广泛的,比如实现无限二级域名功能,提供免费的url转发,在IDC部门实现自动分配免费网址,在大型企业中实现网址分类管理等等,都发挥了巨大的作用。

在阿里云的域名配置如下:

image-20220801145503411

4 server_name匹配规则

我们可以在同一个servername中配置多个域名

1、完整匹配

server中可以配置多个域名,例如:

server_name  test81.chw1113.cn  test82.chw1113.cn;   #域名间使用空格分开

2、通配符匹配

使用通配符的方式如下:

server_name *.chw1113.cn;

需要注意的是精确匹配的优先级大于通配符匹配和正则匹配。

3、通配符结束匹配

使用通配符结束匹配的方式如下:

server_name www.chw1113.*;

4、正则匹配

采用正则的匹配方式如下:

server_name ~^[0-9]+\.chw1113\.cn$;

访问结果如下:

http://12345.chw1113.cn

image-20220801151445536

正则匹配格式

必须以~开头,比如:server_name ~^www\d+\.example\.net$;。如果开头没有~,则nginx认为是精确匹配。在逻辑上,需要添加^$锚定符号。

注意,正则匹配格式中.为正则元字符,如果需要匹配.,则需要反斜线转义。

如果正则匹配中含有{}则需要双引号引用起来,避免nginx报错,如果没有加双引号,则nginx会报如下错误:directive "server_name" is not terminated by ";" in ...

正则表达式全解析+常用示例

正则表达式全解析+常用示例

5、特殊匹配格式

server_name "";
#匹配Host请求头不存在的情况

6、匹配顺序

  1. 精确的名字;
  2. *号开头的最长通配符名称,如 *.example.org
  3. *号结尾的最长通配符名称,如 mail.*;
  4. 第一个匹配的正则表达式(在配置文件中出现的顺序);

7、优化

  • 尽量使用精确匹配;
  • 当定义大量server_name时或特别长的server_name时,需要在http级别调整server_names_hash_max_sizeserver_names_hash_bucket_size,否则nginx将无法启动。

5 反向代理在系统结构中的应用场景

介绍

image-20220801152948188

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

反向代理服务器通常有两种模型,一种是作为内容服务器的替身,另一种作为内容服务器集群的负载均衡器。

  • 作内容服务器的替身

    如果您的内容服务器具有必须保持安全的敏感信息,如信用卡号数据库,可在防火墙外部设置一个代理服务器作为内容服务器的替身。当外部客户机尝试访问内容服务器时,会将其送到代理服务器。实际内容位于内容服务器上,在防火墙内部受到安全保护。代理服务器位于防火墙外部,在客户机看来就像是内容服务器。

    当客户机向站点提出请求时,请求将转到代理服务器。然后,代理服务器通过防火墙中的特定通路,将客户机的请求发送到内容服务器。内容服务器再通过该通道将结果回传给代理服务器。代理服务器将检索到的信息发送给客户机,好像代理服务器就是实际的内容服务器。如果内容服务器返回错误消息,代理服务器会先行截取该消息并更改标头中列出的任何 URL,然后再将消息发送给客户机。如此可防止外部客户机获取内部内容服务器的重定向 URL。

    这样,代理服务器就在安全数据库和可能的恶意攻击之间提供了又一道屏障。与有权访问整个数据库的情况相对比,就算是侥幸攻击成功,作恶者充其量也仅限于访问单个事务中所涉及的信息。未经授权的用户无法访问到真正的内容服务器,因为防火墙通路只允许代理服务器有权进行访问。

  • 作为内容服务器的负载均衡器

    可以在一个组织内使用多个代理服务器来平衡各 Web 服务器间的网络负载。在此模型中,可以利用代理服务器的高速缓存特性,创建一个用于负载平衡的服务器池。此时,代理服务器可以位于防火墙的任意一侧。如果 Web 服务器每天都会接收大量的请求,则可以使用代理服务器分担 Web 服务器的负载并提高网络访问效率。

    对于客户机发往真正服务器的请求,代理服务器起着中间调停者的作用。代理服务器会将所请求的文档存入高速缓存。如果有不止一个代理服务器,DNS 可以采用“轮询法”选择其 IP 地址,随机地为请求选择路由。客户机每次都使用同一个 URL,但请求所采取的路由每次都可能经过不同的代理服务器。

    可以使用多个代理服务器来处理对一个高用量内容服务器的请求,这样做的好处是内容服务器可以处理更高的负载,并且比其独自工作时更有效率。在初始启动期间,代理服务器首次从内容服务器检索文档,此后,对内容服务器的请求数会大大下降。

1、Nginx的反向代理配置

配置如下:

vim /usr/local/nginx/conf/nginx.conf

image-20220801171613859

配置单机域名C:\Windows\System32\drivers\etc\hosts

#nginx测试 begin
192.168.31.253 test80.chw1113.cn
#nginx测试 begin

使用systemctl reload nginx重新加载配置

[root@iZ2ze22yzy03bpdp3jsyqiZ conf]# systemctl reload nginx

访问http://test80.chw1113.cn,确实跳转到了b站

结束之后恢复一下nginx.conf的配置到最开始的状态。

2、基于反向代理的负载均衡器

克隆两个centos,查看克隆出来后的centos的静态ip地址

分别得到静态ip地址为

克隆1:192.168.31.177

克隆2:192.168.31.15

ifconfig

image-20220801165118966

修改clone1的nginx在html目录下的index.html

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
    
<h1>Hello, I'm From clone1 , 192.168.31.177</h1>
<br/>

<h2>Welcome to nginx!</h2>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

修改clone1的nginx在html目录下的index.html

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
    
<h1>Hello, I'm From clone2 , 192.168.31.15</h1>
<br/>

<h2>Welcome to nginx!</h2>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

下面进行访问测试

本体:http://192.168.31.253

克隆1:http://192.168.31.177

克隆2:http://192.168.31.15

访问成功,页面显示符合预期。

2.1 将本体(192.168.31.253)代理到clone1

博主的101对应本体

102对应clone1

103对应clone2

配置本体192.168.31.253的nginx.conf

image-20220801202459662

重新加载nginx配置文件

systemctl reload nginx

测试访问http://192.168.31.253

image-20220801202602813

2.2 配置本体(192.168.31.253)的负载均衡(轮询模式)

在本体(192.168.31.253) 的 nginx.conf 里的 http{ } 里定义一组服务器,要声明在server{}之前

http{
	...
    upstream httpds{
        server 192.168.31.177:80;	#克隆1
        server 192.168.31.15:80;	#克隆2
    }
    ...
    server{...}
}

在 http{ server { location / { 里 } } } 正确配置好代理proxy_pass

http{
	...
	server{
		...
		location / {
			proxy_pass http://httpds;	#这个别名httpds要和上面upstream的别名httpds保持一致
		}
	}
}
image-20220801204706663

重新加载nginx配置文件

systemctl reload nginx

多次访问http://192.168.31.253发现clone1和clone2被交替访问

2.3 配置本体(192.168.31.253)的负载均衡(权重模式)

在本体(192.168.31.253) 的 nginx.conf 里的 http{ } 里定义一组服务器,要声明在server{}之前

http{
	...
    upstream httpds{
        server 192.168.31.177 weight=10;
        server 192.168.31.15 weight=1;
        # server 192.168.31.177 weight=10 down; #down表示不参与负载均衡
        # server 192.168.31.15 weight=1 backup; #backup表示备用服务器,没有服务器可用的时候使用
    }
    ...
    server{...}
}

在 http{ server { location / { 里 } } } 正确配置好代理proxy_pass

http{
	...
	server{
		...
		location / {
			proxy_pass http://httpds;	#这个别名httpds要和上面upstream的别名httpds保持一致
		}
	}
}

测试:

多次访问http://192.168.31.253发现clone1(192.168.31.177)访问的次数多于clone2(192.168.31.15)访问的次数。

2.4 其他负载均衡策略(不常用)

  • ip_hash

    根据客户端的ip地址转发同一台服务器,可以保持会话,但是很少用这种方式去保持会话,例如我们当前正在使用wifi访问,当切换成手机信号访问时,会话就不保持了。

  • least_conn

    最少连接访问,优先访问连接最少的那一台服务器,这种方式也很少使用,因为连接少,可能是由于该服务器配置较低,刚开始赋予的权重较低。

  • url_hash

    根据用户访问的url定向转发请求,不同的url转发到不同的服务器进行处理(定向流量转发)。

  • fair

    根据后端服务器响应时间转发请求,这种方式也很少使用,因为容易造成流量倾斜,给某一台服务器压垮。

6 Nginx动静分离及Rewrite实战

1、动静分离

为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源,如图片、js、css等文件,可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时,代理服务器就可以直接处理,而不用将请求转发给后端服务器。对于用户请求的动态文件,如servlet、jsp,则转发给Tomcat,Jboss服务器处理,这就是动静分离。即动态文件与静态文件的分离。

1.1 动静分离原理

image-20220802061747359

动静分离可通过location对请求url进行匹配,将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。通常将静态资源放到nginx中,动态资源转发到tomcat服务器中。

1.2 Nginx动静分离配置

首先使用宝塔面板安装tomcat

image-20220802062210868

安装完毕开启8080端口,测试访问192.168.31.253:8080,成功访问tomcat首页即可。

image-20220802064645710

D:\AllDownloads\BaiduNetdiskDownload\nginx相关中的charts-project.zip解压并放入centos的如下位置

/www/server/tomcat/webapps/ROOT

image-20220802063237727

再次访问得到页面

image-20220802064715437

配置clone1(192.168.31.177)的反向代理:

前往clone1(192.168.31.177)的nginx.conf文件,编辑内容

http{
	...
	server {
		...
		location / {
			proxy_pass http://192.168.31.253:8080;
		}
	}

}
image-20220802065516530

使用systemctl reload nginx重新加载配置

systemctl reload nginx

前往本体(192.158.31.253)将/www/server/tomcat/webapps/的images文件夹删除,

现在访问clone1(192.168.31.177),发现图片访问不到了:

image-20220802065800429

下面将静态资源配置到代理服务器 clone1(192.168.31.177)中的/www/resources目录下

image-20220802071719667

配置clone1(192.168.31.177) 的nginx.cfg

http {
	...
	server {
		...
		location /images {
			root /www/resources;
			index index.html index.htm;
		}
	}
}
image-20220802071916392

现在访问clone1(192.168.31.177),发现图片又出现了。

image-20220802072154569

上面通过将静态文件放到另一个服务器上并配置了nginx.conf实现反向代理并实现把主机的静态资源分离出来。

1.3 使用正则配置动静分离

1.3.1 常见的Nginx正则表达式
表达式作用
^匹配输入字符串的起始位置
$匹配输入字符串的结束位置
*匹配前面的字符零次或多次。如ol*能匹配oololl
+匹配前面的字符一次或多次。如ol+能匹配olollolll,但不能匹配o
?匹配前面的字符零次或一次。例如do(es)?能匹配do或者does?等效于{0,1}
.匹配除\n外的任何单个字符,若要匹配包括\n在内的任意字符,请使用诸如[.\n]之类的模式
\将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如\n匹配一个换行符,而\$则匹配$
\d匹配纯数字
{n}重复 n 次
{n,}重复 n 次或更多次
{n,m}重复 n 到 m 次
[ ]定义匹配的字符范围
[c]匹配单个字符 c
[a-z]匹配 a-z 小写字母的任意一个
[a-zA-Z0-9]匹配所有大小写字母或数字
( )表达式的开始和结束位置
|或运算符,如 (js|img|css)
1.3.2 location正则
//location大致分为三类
精准匹配:location = /{}
一般匹配:location /{}
正则匹配:location ~/{}

//location常用的匹配规则
= :进行普通字符精确匹配,也就是完全匹配;
^~ :表示前缀字符串匹配(不是正则匹配,需要使用字符串),如果匹配成功,则不再匹配其它 location;
~ :区分大小写的匹配(需要使用正则表达式);
~* :不区分大小写的匹配(需要使用正则表达式);
!~ :区分大小写的匹配取非(需要使用正则表达式);
!~* :不区分大小写的匹配取非(需要使用正则表达式);

//优先级
1、精确匹配 =
2、前缀匹配 ^~
3、按文件中顺序的正则匹配 ~~*
4、匹配不带任何修饰的前缀匹配
5、交给 / 通用匹配

注意:

精确匹配: = , 后面的表达式中写的是纯字符串
字符串匹配: ^~ 和 无符号匹配 , 后面的表达式中写的是纯字符串
正则匹配: ~ 和 ~* 和 !~ 和 !~* , 后面的表达式中写的是正则表达式

1.3.3 location的说明
  1. location = / {},= 为精确匹配 / ,主机名后面不能带任何字符串。
    • 如访问 / 和 /data,则 / 匹配,/data 不匹配。
    • location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。
    • location /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/ 。
  2. location / {}
    因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
    但若后面是正则表达式会和最长字符串优先匹配(最长匹配)。
  3. location /documents/ {}
    匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
    只有其它 location 后面的正则表达式没有匹配到时,才会采用这一条。
  4. location /documents/abc {}
    匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
    只有其它 location后面的正则表达式没有匹配到时,才会采用这一条。
  5. location ^~ /images/ {}
    匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
  6. location ~* \.(gif|jpg|jpeg)$ {}
    匹配所有以 .gif、.jpg或 .jpeg 结尾的请求
    然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则
  7. location /images/abc {}
    最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在
  8. location ~ /images/abc {}
    匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条
  9. location /images/abc/1.html {}
    匹配/images/abc/1.html 文件,如果和正则 ~ /images/abc/1.html 相比,正则优先级更高

优先级总结:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (location /)

1.3.4 实际中至少使用三个匹配规则
  • 第一个必选规则

    直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。这里是直接转发给后端应用服务器了,也可以是一个静态首页。

    location = / {
        proxy_pass http://127.0.0.1:8080/;
    }
    
  • 第二个必选规则

    处理静态文件请求,这是nginx作为http服务器的强项,有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用。

    location ^~ /static/ {
        root /webroot/static/;
    }
    
    location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)${
        root /webroot/res/;
    }
    
  • 第三个规则
    通用规则,用来转发动态请求到后端应用服务器

    location /api/ {
        proxy_pass http://127.0.0.1:3000/api/
    }
    

2、URLRewrite

rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记。

2.1 rewrite格式

image-20220803120708696

2.2 URLRewrite的优缺点

优点:掩藏真实的url以及url中可能暴露的参数,以及隐藏web使用的编程语言,提高安全性便于搜索引擎收录

缺点:降低效率,影响性能。如果项目是内网使用,比如公司内部软件,则没有必要配置。

2.3 实例

在clone1(192.168.31.177)中的nginx.conf添加rewrite指令

rewrite ^/test.html$ /index.html?testParam=3 break;

//也可以使用regex形式
rewrite ^/[0-9]+.html$ /index.html?testParam=$1 break; //$1表示第一个匹配的字符串
image-20220803121558854

测试访问http://192.168.31.177/test.html

image-20220803122712984

地址栏显示我们访问的是http://192.168.31.177/test.html,但实际前往的其实是192.168.31.177然后反向代理到192.168.31.253:8080。

3、负载均衡+URLRewrite实战

查看防火墙是否开启

firewall-cmd --state

开启本体(192.168.31.253)的防火墙

systemctl reload nginx

查看已配置规则

firewall-cmd --list-all

添加指定端口和ip访问(添加之后需要重启防火墙),针对某个 IP 开放端口

firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.31.177" port protocol="tcp" port="8080" accept"

移除指定端口和ip的访问规则,针对某个 IP 关闭端口

firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.31.177" port protocol="tcp" port="8080" accept"

重启防火墙

firewall-cmd --reload

测试直接访问192.168.31.253:8080,应该是不可以访问的,因为防火墙只针对clone1开放了8080端口。

image-20220803125730667

访问192.168.31.177:80/test.html

image-20220803125928338

使用负载均衡式访问,注意还要先向clone2开放8080端口

image-20220803130012593

7 Nginx配置防盗链

0、什么是盗链?

盗链是指服务提供商不提供服务内容,而是通过技术手段绕过限制,直接向终端用户提供其他服务提供商的内容,利益自己独享,代价却由其他服务提供商承担的一种恶意行为。

1、Nginx防盗链配置

为了模拟盗链,在这里让本体(192.168.31.253)为服务站点,clone1(192.168.31.177)为网关服务器,clone2(192.168.31.15)访问clone1进行盗链。

本体(192.168.31.253)的nginx.conf

image-20220803141502299

网关服务器clone1(192.168.31.177)的nginx.conf

image-20220803141621639

盗链者clone2(192.168.31.15)的nginx.conf

image-20220803141940055
systemctl reload nginx
#重新加载nginx服务

此时访问clone2(192.168.31.15)的地址就可以得到clone1的服务

image-20220803142410704

知识点小回顾

location ^~ /images/ {}
#匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条

如果不想被盗链,可以对网关服务器clone1(192.168.31.177)做如下配置:

location / { ... }
location ^~/images {
#valid_referers 指令,配置是否允许 referer 头部以及允许哪些 referer 访问。
#192.168.8.102不是ip而是域名(去掉http:// 前缀)
valid_referers 192.168.31.177;
if ($invalid_referer) { # 注意这里if后要加空格
	return 403; ## 返回错误码
}
root  /www/resources;
}
image-20220803144435849

此时再访问http://192.168.31.15/就显示不出来静态资源了。

1.1 valid_referers解释(valid有效的)

可以同时携带多个参数,表示多个 referer 头部都生效。

参数值

  • none:允许没有 referer 信息的请求访问,即直接通过url访问。
  • blocked:请求头Referer字段不为空(即存在Referer),但是值可以为空(值被代理或者防火墙删除了),并且允许refer不以“http://”或“https://”开头,通俗点说就是允许“http://”或"https//"以外的请求。
  • server_names:若 referer 中站点域名与 server_name 中本机域名某个匹配,则允许该请求访问。
  • 其他字符串类型:检测referer与字符串是否匹配,如果匹配则允许访问,可以采用通配符*。
  • 正则表达式:若 referer 的值匹配上了正则,就允许访问。

valid_referers设置为none的情况

location ^~/images/ {
	valid_referers none 192.168.31.177;
	if ($invalid_refer) {
		return 403;
	}
}

valid_referers配置了none之后,可以直接通过全称的url访问到静态资源。

image-20220803150113511

此时就可以直接访问 192.168.31.177/images/bg.jpg 这个静态资源

image-20220803150231129

1.2 invalid_referer 变量

  • 允许访问时变量值为空
  • 不允许访问时变量值为1

如:

location / {
	valid_referers none server_names *.test.com www.test.org.cn/nginx/;
	if ($invalid_referer){	# 若referer头部是无效的则invalid_referer值就是1,进入if体
		return 403;	# 返回错误代码
	}
}

2、使用curl测试

windows终端输入

curl -I http://192.168.31.177/images/bg.jpg
# -I 参数则只显示 http response 的头信息。

返回结果

C:\Users\Administrator>curl -I http://192.168.31.177/images/bg.jpg
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Wed, 03 Aug 2022 07:05:27 GMT
Content-Type: image/jpeg
Content-Length: 519806
Last-Modified: Mon, 01 Aug 2022 23:17:00 GMT
Connection: keep-alive
ETag: "62e85eec-7ee7e"
Accept-Ranges: bytes

用curl指令将请求标头Referer设置为"http://baidu.com"

curl -e "http://baidu.com" -I http://192.168.31.177/images/bg.jpg
# -e参数用来设置 HTTP 的标头Referer,表示请求的来源

返回结果

C:\Users\Administrator>curl -e "http://baidu.com" -I http://192.168.31.177/images/bg.jpg
HTTP/1.1 403 Forbidden
Server: nginx/1.21.6
Date: Wed, 03 Aug 2022 07:10:14 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

综上,发现Referer标头成为了访问资源的通行证。

如果去clone1(192.168.31.177)中的nginx.conf的valid_referers添加baidu.com,就又可以访问成功了

image-20220803151325883

C:\Users\Administrator>curl -e "http://baidu.com" -I http://192.168.31.177/images/bg.jpg
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Wed, 03 Aug 2022 07:13:42 GMT
Content-Type: image/jpeg
Content-Length: 519806
Last-Modified: Mon, 01 Aug 2022 23:17:00 GMT
Connection: keep-alive
ETag: "62e85eec-7ee7e"
Accept-Ranges: bytes

3、配置错误提示页面

3.1 返回错误页面

在clone1(192.168.31.177)的nginx的html目录中添加403.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Error</title>
    <style>
        html {
            color-scheme: light dark;
        }

        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
</head>
<body>
<h1>An error occurred.</h1>
<p>非法请求.</p>

</body>
</html>

image-20220803151820564

修改clone1(192.168.31.177)的nginx.conf(先把valid_referers的none值去掉)

error_page	403		/403.html;
location = /403.html	{
	root html;
}

image-20220803152014133

(确保valid_referers的none已经去掉)访问http://192.168.31.177/images/bg.jpg

image-20220803152347988

3.2 返回出错图片

修改clone1(192.168.31.177)的nginx.conf

location ^~/images {
	valid_referers 192.168.31.177 baidu.com;
    if ($invalid_referer) {
    	rewrite ^/  /images/403.png break;
    	# ^后跟着匹配输入字符串的起始位置"/"
    	# flag标记:break,本条规则匹配完成即终止,不再匹配后面任何规则
    }
}
image-20220803153406504

将403.png保存到/www/resources/images中

image-20220803153600244

访问盗链者clone2(192.168.31.15),http://192.168.31.15

image-20220803153705295

8 Nginx高可用及Keepalived实战

1、高可用场景及解决方案

Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。所以,Keepalived 一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

keepalived官网http://www.keepalived.org

keepalived服务的三个重要功能:

  • 管理LVS负载均衡软件
  • 实现LVS集群节点的健康检查
  • 作为系统网络服务的高可用性(failover)

2、安装keepalived

centos安装命令:

yum install -y keepalived

安装成功截图:

image-20220803161538029

3、keepalived实战

keepalived的配置文件keepalived.conf所在目录 /etc/keepalived/

image-20220803161709519

在当前实战中,主Nginx为本体(192.168.31.253),备用机为clone1(192.168.31.177)。

首先需要修改主Nginx(192.168.31.253)的keepalived.conf配置

vim /etc/keepalived/keepalived.conf

已在windows桌面保存keepalived.conf副本文件

! Configuration File for keepalived

global_defs {
   router_id LB_102
}

vrrp_instance VI_102 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.200
    }
}

使用systemctl start keepalived启动keepalived

systemctl start keepalived  #启动keepalived
systemctl status keepalived  #查看状态

查看ip发现多了虚拟ip192.168.31.200:

ip addr

image-20220803164503959

备用机clone1(192.168.31.177)的keepalived.conf配置

! Configuration File for keepalived

global_defs {
   router_id LB_101
}

vrrp_instance VI_102 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.200
    }
}

使用systemctl start keepalived启动keepalived

systemctl start keepalived  #启动keepalived
systemctl status keepalived  #查看状态

查看ip同样发现多了虚拟ip192.168.31.200:

image-20220803165235054

测试访问虚拟地址:192.168.31.200,成功显示页面。

image-20220803170201496

下面关闭clone1服务器,并再次访问192.168.31.200。(注意检查本体防火墙有没有放行端口8080)

image-20220803171604345

可以看到clone1服务器宕机后,仍然可以从本体访问(本体的静态文件已经被分离出去了,所以这里没有加载出来图片),keepalived配置成功。

)的keepalived.conf配置

vim /etc/keepalived/keepalived.conf

已在windows桌面保存keepalived.conf副本文件

! Configuration File for keepalived

global_defs {
   router_id LB_102
}

vrrp_instance VI_102 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.200
    }
}

使用systemctl start keepalived启动keepalived

systemctl start keepalived  #启动keepalived
systemctl status keepalived  #查看状态

查看ip发现多了虚拟ip192.168.31.200:

ip addr

[外链图片转存中…(img-50eSn0UG-1660116185593)]

备用机clone1(192.168.31.177)的keepalived.conf配置

! Configuration File for keepalived

global_defs {
   router_id LB_101
}

vrrp_instance VI_102 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.31.200
    }
}

使用systemctl start keepalived启动keepalived

systemctl start keepalived  #启动keepalived
systemctl status keepalived  #查看状态

查看ip同样发现多了虚拟ip192.168.31.200:

[外链图片转存中…(img-OxJSgTs5-1660116185594)]

测试访问虚拟地址:192.168.31.200,成功显示页面。

[外链图片转存中…(img-dfezIRYr-1660116185595)]

下面关闭clone1服务器,并再次访问192.168.31.200。(注意检查本体防火墙有没有放行端口8080)

[外链图片转存中…(img-5IHM5xJW-1660116185596)]

可以看到clone1服务器宕机后,仍然可以从本体访问(本体的静态文件已经被分离出去了,所以这里没有加载出来图片),keepalived配置成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值