nginx变量+rewrite相关功能+反向代理+openresty

目录

1、nginx变量

(1)内置变量

 示例

(2)自定义变量

示例

2、nginx中的rewrite模块功能

(1)ngx_http_rewrite_module 模块指令

1)if指令 

示例

2)set指令

 示例​编辑

3)break指令

示例

4)return指令

示例

(2)rewrite指令

1)rewrite flag

2)案例: 域名永久与临时重定向

3)案例: break 与 last

a)添加break

b)添加last

c)指定目录后添加

4)案例: 自动跳转 https -- 全站加密

(3)防盗链

实现盗链 

实现防盗链 

3、nginx反向代理功能

(1)实现 http 反向代理

http 协议反向代理

a)反向代理配置参数

b)案例

案例一 指定 location 实现反向代理

案例二 动静分离,针对特定的资源实现代理

案例三 反向代理示例: 缓存功能

(2)http 反向代理负载均衡

http upstream配置参数

案例

4、实现nginx四层负载均衡

(1)TCP负载均衡

(2)负载均衡实例:MySQL 

5、实现FastCGI

(1)配置指令

(2)源码编译php

(3)php相关配置优化

(4)nginx和php的整合

(5)nginx-php的缓存优化

(6)nginx-memcache高速缓存

6、nginx二次开发版本


1、nginx变量

  • nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
  • 变量可以分为内置变量和自定义变量
  • 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值

(1)内置变量

        $remote_addr;        #存放了客户端的地址,注意是客户端的公网IP

        $args;                      #变量中存放了URL中的所有参数

        $is_args                  #如果有参数为? 否则为空

        $document_root;     #保存了针对当前资源的请求的系统根目录,

        $document_uri;       #保存了当前请求中不包含参数的URI,注意是不包含请求的指令 #比如:http://lee.zx.org/var?\id=11111会被定义为/var #返回结果为:/var

        $host;                      #存放了请求的host名称

        $remote_port;         #客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口

        $remote_user;         #已经经过Auth Basic Module验证的用户名

        $request_body_file; #做反向代理时发给后端服务器的本地资源的名称

        $request_method;   #请求资源的方式,GET/PUT/DELETE等

        $request_filename; #当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径, #如:webdata/nginx/zx.org/lee/var/index.html

        $request_uri;          #包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args, #例如:/main/index.do?id=20190221&partner=search

        $scheme;                     #请求的协议,例如:http,https,ftp等

        $server_protocol;         #保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0等

        $server_addr;              #保存了服务器的IP地址

        $server_name;            #虚拟主机的主机名

        $server_port;               #虚拟主机的端口号

        $http_user_agent;       #客户端浏览器的详细信息

        $http_cookie;               #客户端的所有cookie信息

        $cookie_<name>         #name为任意请求报文首部字部cookie的key名

        $http_<name>             #name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有横线需要替换为下划线

        $arg_<name>             #此变量存放了URL中的指定参数,name为请求url中指定的参数 

[root@nginx conf.d]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx conf.d]# 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 conf.d]# nginx -s reload

 示例

(2)自定义变量

        需要自定义变量名称和值,使用指令set $variable value;    

Syntax: set $variable value;
Default: —
Context: server, location, if

示例

2、nginx中的rewrite模块功能

  • Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
  • 此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
  • rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
  • 比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的 链接,就可以设置为访问
  • 另外还可以在一定程度上提高网站的安全性。

(1)ngx_http_rewrite_module 模块指令

1)if指令 

if (条件匹配) {
    action
}

        用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断

使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间
使用以下符号链接:
=         #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!=        #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~         #区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~        #区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~*        #不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~*       #不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)

#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
示例
[root@nginx sbin]# ll -d /data/web/html/test2
ls: cannot access '/data/web/html/test2': No such file or directory

[root@nginx conf.d]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx conf.d]# 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 conf.d]# nginx -s reload
[root@nginx conf.d]# cat /root/usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name var.zx.org;
    root /data/web/html;
    index index.html;

    location /var {
        default_type text/html;
        set $zx zz;
        echo $zx;
    }
	location /test2 {
    if ( !-e $request_filename ){
        echo "$request_filename is not exist";
    }
  }
}

[root@nginx conf.d]# curl var.zx.org/test2
/data/web/html/test2 is not exist

2)set指令

指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key,另外set定义格式为set $key value,value可以是text, variables和两者的组合

 示例

3)break指令

  • 用于中断当前相同作用域(location)中的其他Nginx配置
  • 与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
  • 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
  • Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用

注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行

示例

4)return指令

        return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置

return code;        #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容
                    #可以调用变量,其中text如果有空格,需要用单或双引号
return code URL;    #返回给客户端的URL地址
示例

可在浏览器直接访问var.zx.org/return直接调转到百度

[root@nginx conf.d]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# cat /root/usr/local/nginx/conf.d/vhost.conf 
server {
    listen 80;
    server_name var.zx.org;
    root /data/web/html;
    index index.html;

    location /var {
        default_type text/html;
        set $zx zz;
        echo $zx;
    }
	 location /return {
        default_type text/html;
        if ( !-e $request_filename){
            return 301 http://www.baidu.com;
        }
        echo "$request_filename is exist";
    }

}

(2)rewrite指令

        通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理

        rewrite将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI 注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成 后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的 标志位用于控制此循环机制 如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301

语法格式:rewrite regex replacement [flag];
.      #匹配除换行符以外的任意字符
\w     #匹配字母或数字或下划线或汉字
\s     #匹配任意的空白符
\d     #匹配数字
\b     #匹配单词的开始或结束
^      #匹配字付串的开始
$      #匹配字符串的结束
*      #匹配重复零次或更多次
+      #匹配重复一次或更多次
?      #匹配重复零次或一次
(n)    #匹配重复n次
{n,}   #匹配重复n次或更多次
{n,m}  #匹配重复n到m次
*?     #匹配重复任意次,但尽可能少重复
+?     #匹配重复1次或更多次,但尽可能少重复
??     #匹配重复0次或1次,但尽可能少重复
{n,m}? #匹配重复n到m次,但尽可能少重复
{n,}?  #匹配重复n次以上,但尽可能少重复
\W     #匹配任意不是字母,数字,下划线,汉字的字符
\S     #匹配任意不是空白符的字符
\D     #匹配任意非数字的字符
\B     #匹配不是单词开头或结束的位置
[^x]   #匹配除了x以外的任意字符
[^lee] #匹配除了magedu 这几个字母以外的任意字符

1)rewrite flag

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

  • 跳转型指由客户端浏览器重新对新地址进行请求
  • 代理型是在WEB服务器内部实现跳转
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302

permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301

break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作
#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用
#适用于一个URL一次重写

last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,
#而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户

2)案例: 域名永久与临时重定向

永久重定向301:域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录可以缓存到 客户端浏览器 永久重定向会缓存DNS解析记录, 浏览器中有 from disk cache 信息,即使nginx服务器无法访问,浏览器也会利用缓存进行重定向

域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器 不会缓存当前域名的解析记录,而浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最大的本质区别。 即当nginx服务器无法访问时,浏览器不能利用缓存,而导致重定向失败 

3)案例: break 与 last

访问break请求被rewrite至test1,而访问test1转递请求再次被rewrite发送至test2,此测试last和break 分别有什么区别

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

a)添加break

b)添加last

c)指定目录后添加
[root@nginx web]# mkdir -p /data/web/test1
[root@nginx web]# echo test1 > /data/web/test1/index.html

4)案例: 自动跳转 https -- 全站加密

将在不影响用户请求情况下将http请求全部自动跳转至 https,另外也可以实现部分 location 跳转

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

    location / {
        if ( $scheme = http ){
            rewrite / https://$host redirect;
        }
    }
}

# 优化版:判断文件是否存在
# 当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页
server {
    listen 80;
    listen 443 ssl;
    server_name www.timinglee.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/timinglee.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/timinglee.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;
        }
    }

(3)防盗链

防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名,正常的referer信息有以下几种

none:               #请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked:            #请求报文有referer首部,但无有效值,比如为空。
server_names:       #referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string:   #自定义指定字符串,但可使用*作通配符。示例: *.timinglee.org、www.timinglee.*
regular expression: #被指定的正则表达式模式匹配到的字符串,要使用~开头,例如~.*:~\.timinglee\.com
实现盗链 
#新建一个主机172.25.254.10,盗取另一台主机www.zx.org/images/dog.png的图片
[root@test ~]# yum install httpd -y
[root@test ~]# cd /var/www/html
[root@test html]# ls
[root@test html]# vim index.html
[root@test html]# systemctl start httpd
[root@test html]# cat index.html 
<html>

  <head>
    <meta http-equiv=Content-Type content="text/html;charset=utf-8">
    <title>盗链</title>
</head>

  <body>
    <img src="http://www.zx.org/images/dog.png" >
    <h1 style="color:red">欢迎大家</h1>
    <p><a href=http://www.zx.org>zzzz</a>xxxxx</p>
  </body>

</html>

#重启apache并访问http://172.25.254.10 测试
#验证两个域名的日志,是否会在被盗连的web站点的日志中出现以下盗链日志信息

实现防盗链 

当对方想链接本站网站图片,可使用rewrite指令跳转到另外一张图片,使对方获取不到原本想要的图片,从而达到防盗链的效果。

[root@nginx ~]# cd /data/web/html/
[root@nginx html]# ls
break  images  index.html  last  test1  test2  daolian.jpg
server {
    listen 80;
    listen 443 ssl;
    server_name www.zx.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/zx.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/zx.org.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
	
	location /images  {
        valid_referers none blocked server_names *.zx.org ~/.baidu/.;
        if ( $invalid_referer ){
                rewrite ^/   http://www.zx.org/dog.png;
        }
    }
}

3、nginx反向代理功能

        ——代理将客户端的请求分发给某个服务器

        ——指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的 一种方式,这是用的比较多的一种方式

Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预 定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主 要在不同的场景使用以下模块实现不同的功能

ngx_http_proxy_module:     #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module   #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组
ngx_stream_proxy_module:   #将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module:   #将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module:     #将客户端对Python的请求以uwsgi协议转发至指定服务器处理

同构代理:用户不需要其他程序的参与,直接通过http协议或者tcp协议访问后端服务器

异构代理:用户访问的资源时需要经过处理后才能返回的,比如php,python,等等,这种访问资源需要经过处理才能被访问

(1)实现 http 反向代理

http 协议反向代理

a)反向代理配置参数
proxy_pass; #用来设置将客户端请求转发给的后端服务器的主机,可以是主机名(将转发至后端服务做为主机头首部)、IP地址:端口的方式,也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持

proxy_hide_header field; #用于nginx作为反向代理的时候,在返回给客户端http响应时,隐藏后端服务器相应头部的信息,可以设置在http,server或location块

proxy_pass_header field; #透传,默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端,field 首部字段大小不敏感

proxy_pass_request_body on | off;    #是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启

proxy_pass_request_headers on | off;   #是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启

proxy_set_header;    #可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部

proxy_connect_timeout time;    #配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒

proxy_read_timeout time;    #配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s

proxy_send_timeout time;    #配置nginx项后端服务器或服务器组发起write请求后,等待的超时 时间,默认60s

proxy_http_version 1.0;    #用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0

proxy_ignore_client_abort off;    #当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器、会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并立即记录499日志,默认为off
b)案例
案例一 指定 location 实现反向代理
[root@ka1 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@ka2 ~]# mkdir -p /var/www/html/static
[root@ka2 ~]# echo static 172.25.254.20 >/var/www/html/static/index.html
[root@ka2 ~]# vim /etc/httpd/conf/httpd.conf     # 更改listen端口为8080
[root@ka2 ~]# systemctl restart httpd
[root@nginx ~]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /root/usr/local/nginx/conf.d/vhost.conf 
server {
	listen 80;
	server_name www.zx.org;

	location / {
		proxy_pass http://172.25.254.10:80;
	}
	location /static {
		proxy_pass http://172.25.254.20:8080;
	}
}

案例二 动静分离,针对特定的资源实现代理
[root@ka1 ~]# yum install php -y
[root@ka1 ~]# systemctl restart httpd
[root@ka1 ~]# vim /var/www/html/index.php
[root@ka1 ~]# cat /var/www/html/index.php
<?php
	phpinfo();
?>

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

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

案例三 反向代理示例: 缓存功能

缓存功能默认关闭状态,需要先动配置才能启用

proxy_cache zone_name | off; 默认off    #指明调用的缓存,或关闭缓存机制;Context:http, server, location#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义

proxy_cache_key string;    #缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;

proxy_cache_valid [code ...] time;    #定义对特定响应码的响应内容的缓存时长,定义在http{...}中

proxy_cache_path;    #定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx ~]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /root/usr/local/nginx/conf.d/vhost.conf 
server {
	listen 80;
	server_name www.zx.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 ~]# ll /usr/local/nginx/proxy_cache/ -d
drwx------ 2 nginx root 6 Aug 19 08:08 /usr/local/nginx/proxy_cache/
[root@nginx ~]# tree /usr/local/nginx/proxy_cache/ 

非缓存场景压测: 

访问并验证缓存文件: 

(2)http 反向代理负载均衡

上文中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测。

Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能

http upstream配置参数

#自定义一组服务器,配置在http块内
upstream name {
server .....
......
}

server address [parameters];    #配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置
#server支持的parameters如下:
weight=number     #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number  #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number  #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup            #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down              #标记为down状态,可以平滑下线后端服务器
resolve           #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
hash KEY [consistent];        #基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid        #基于cookie中的sessionid这个key进行hash调度,实现会话绑定
ip_hash;                      #源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持
least_conn;                   #最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC
案例
[root@ka1 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@ka1 ~]# systemctl enable --now httpd
[root@ka2 ~]# echo 172.25.254.20 > /var/www/html/index.html
[root@ka2 ~]# systemctl enable --now httpd

[root@nginx ~]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /root/usr/local/nginx/conf.d/vhost.conf 
upstream webcluster {
	#ip_hash;
	hash $request_uri consistent;
	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.110 backup;
}
server {
	listen 80;
	server_name www.zx.org;

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

4、实现nginx四层负载均衡

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

(1)TCP负载均衡

[root@ka1 named]# vim /etc/named.conf 

[root@ka1 named]# vim /etc/named.rfc1912.zones

[root@ka1 ~]# yum install bind -y
[root@ka2 ~]# yum install bind -y
[root@ka1 ~]# cd /var/named/
[root@ka1 named]# chgrp named zx.org.zone
[root@ka1 named]# cp named.localhost zx.org.zone
[root@ka1 named]# vim zx.org.zone 
[root@ka1 named]# systemctl start named
[root@ka1 named]# cat zx.org.zone             # ka2同操作,IP地址改成172.25.254.20
$TTL 1D
@	IN SOA	ns.zx.org.	root.zx.org. (
					0	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
	NS		ns.zx.org.
ns	A		172.25.254.10
www	A		172.25.254.10

[root@ka1 named]# dig www.zx.org @172.25.254.10
[root@ka1 named]# dig www.zx.org @172.25.254.20
[root@ka1 named]# scp -p /etc/named.{conf,rfc1912.zones} root@172.25.254.20:/etc/ 
[root@ka1 named]# scp -p /var/named/zx.org.zone root@172.25.254.20:/var/named/zx.org.zone
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf

[root@nginx ~]# vim /root/usr/local/nginx/conf.d/vhost.conf 
[root@nginx ~]# cat /root/usr/local/nginx/conf.d/vhost.conf 
upstream webcluster {
	#ip_hash;
	#hash $request_uri consistent;
	hash $cookie_hello;
	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.110 backup;
}

server {
	listen 80;
	server_name www.zx.org;

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

[root@nginx ~]# mkdir -p /usr/local/nginx/tcpconf.d/
[root@nginx ~]# cd /usr/local/nginx/tcpconf.d/
[root@nginx ~]# vim dns.conf
[root@nginx tcpconf.d]# cat 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 tcpconf.d]# 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 tcpconf.d]# nginx -s reload

[root@nginx ~]# netstat -antlupe | grep 53
tcp6       0      0 ::1:6011                :::*                    LISTEN      0          2753      1818/sshd: root@pts 
udp        0      0 0.0.0.0:53              0.0.0.0:*                           0          60428      1007/nginx: master  
udp        0      0 0.0.0.0:53              0.0.0.0:*                           0          60427      1007/nginx: master  
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           70         23214      854/avahi-daemon: r 
udp6       0      0 :::5353                 :::*                                70         23215      854/avahi-daemon: r 


[root@nginx ~]# dig www.zx.org @172.25.254.110

; <<>> DiG 9.16.23-RH <<>> www.zx.org @172.25.254.110
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 46262
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: f379f4ad4e910f42c34cee6a66c2cdff2fb4580c3fd45eb5 (good)
;; QUESTION SECTION:
;www.zx.org.			IN	A

;; Query time: 3 msec
;; SERVER: 172.25.254.110#53(172.25.254.110)
;; WHEN: Mon Aug 19 12:45:51 CST 2024
;; MSG SIZE  rcvd: 67

(2)负载均衡实例:MySQL 

[root@ka1 ~]# yum install mariadb-server -y
[root@ka2 ~]# yum install mariadb-server -y
[root@nginx ~]# dnf install mariadb -y
[root@ka1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@ka1 ~]# systemctl start mariadb
[root@ka2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@ka2 ~]# systemctl start mariadb

[root@ka1 ~]# mysql -e "grant all on *.* to zx@'%' identified by 'zx';"
[root@ka2 ~]# mysql -e "grant all on *.* to zx@'%' identified by 'zx';"

[root@ka1 ~]# mysql -uzx -pzx -h172.25.254.20 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|          20 |
+-------------+
[root@ka2 ~]# mysql -uzx -pzx -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|          10 |
+-------------+

 

[root@nginx tcpconf.d]# vim dns.conf 
[root@nginx tcpconf.d]# 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 tcpconf.d]# nginx -s reload
[root@nginx tcpconf.d]# cat 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 udp reuseport;
        listen 172.25.254.110:3306;
        proxy_timeout 20s;
        proxy_pass mysql;
    }
	server {
    	listen 53 udp reuseport;
    	proxy_timeout 20s;
    	proxy_pass dns;
	}
}

[root@nginx tcpconf.d]# netstat -antlupe | grep 3306
udp        0      0 0.0.0.0:3306            0.0.0.0:*                           0          62882      1007/nginx: master  
udp        0      0 0.0.0.0:3306            0.0.0.0:*                           0          62881      1007/nginx: master  

[root@ka1 ~]# mysql -uzx -pzx -h172.25.254.110 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|          10 |
+-------------+
[root@ka2 ~]# mysql -uzx -pzx -h172.25.254.110 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|          10 |
+-------------+

在ka2处停止MySQL服务,多次测试访问,只会看到mysql-ka1.zx.org进行响应

[root@ka2 ~]# systemctl stop mariadb.service

5、实现FastCGI

实验环境

PS C:\Users\qq358\Desktop> scp .\memc-nginx-module-0.20.tar.gz root@172.25.254.110:/root
PS C:\Users\qq358\Desktop> scp .\srcache-nginx-module-0.33.tar.gz root@172.25.254.110:/root
[root@nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz 
[root@nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz 
[root@nginx nginx-1.26.1]# ./configure --help | less
[root@nginx nginx-1.26.1]# cd nginx-1.26.1/
[root@nginx 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]# make && make install
[root@nginx nginx-1.26.1]# ps aux | grep nginx
avahi        854  0.0  0.3  15532  6136 ?        Ss   Aug19   0:02 avahi-daemon: running [nginx.local]
root        1007  0.0  0.3  31472  6216 ?        Ss   Aug19   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx       5460  0.0  0.3  34940  5564 ?        S    00:01   0:00 nginx: worker process
nginx       5461  0.0  0.3  34940  5564 ?        S    00:01   0:00 nginx: worker process
nginx       5462  0.0  0.2  34940  5200 ?        S    00:01   0:00 nginx: cache manager process
root        9479  0.0  0.1 221796  2252 pts/2    S+   09:25   0:00 grep --color=auto nginx
[root@nginx nginx-1.26.1]# 
[root@nginx nginx-1.26.1]# killall -9 nginx
[root@nginx nginx-1.26.1]# ps aux | grep nginx
avahi        854  0.0  0.3  15532  6136 ?        Ss   Aug19   0:02 avahi-daemon: running [nginx.local]
root        9488  0.0  0.1 221796  2240 pts/2    S+   09:26   0:00 grep --color=auto nginx
[root@nginx nginx-1.26.1]# kill -9 854
[root@nginx nginx-1.26.1]# nginx
[root@nginx nginx-1.26.1]# nginx -v
nginx version: nginx/1.26.1

(1)配置指令

Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理

fastcgi_pass address:port;                       #转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in location
fastcgi_index name;                              #fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];    #设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name

(2)源码编译php

PS C:\Users\qq358\Desktop> scp .\php-8.3.9.tar.gz root@172.25.254.110:/root
[root@nginx ~]# tar zxf php-8.3.9.tar.gz 

# 解决php依赖
[root@nginx php-8.3.9]# dnf whatprovides */libsystemd*
[root@nginx php-8.3.9]# dnf install systemd-devel -y
[root@nginx php-8.3.9]# dnf install libcurl-devel -y
[root@nginx php-8.3.9]# yum install libpng-devel -y
[root@nginx php-8.3.9]# cd /mnt/
[root@nginx mnt]# 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 mnt]# dnf install oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
[root@Nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel oniguruma-devel

#解压源码并安装
[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-sockets  --enable-soap  --enable-xml  --enable-ftp  --enable-gd   --enable-exif   --enable-mbstring   --enable-bcmath  --with-fpm-systemd
[root@nginx php-8.3.9]# make && make install


 

(3)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
[root@nginx etc]# cd php-fpm.d/
[root@nginx php-fpm.d]# ls
www.conf.default
[root@nginx php-fpm.d]# cp www.conf.default www.conf -p
[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 ~]# cd /usr/local/php/etc/
[root@nginx etc]# vim php.ini            # 添加Asia/Shanghai,修改时区
[root@nginx fpm]# 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    #注释ProtectSystem=full
[root@nginx fpm]# systemctl daemon-reload 
[root@nginx fpm]# systemctl start php-fpm
[root@nginx fpm]# netstat -antlupe | grep php
[root@nginx fpm]# cd /usr/local/php/etc/php-fpm.d/
[root@nginx php-fpm.d]# vim www.conf        # 更改listen = 0.0.0.0:9000
[root@nginx php-fpm.d]# systemctl restart php-fpm
[root@nginx php-fpm.d]# netstat -antlupe | grep php

(4)nginx和php的整合

[root@nginx ~]# mkdir -p /data/web/php
[root@nginx ~]# vim ~/.bash_profile 
[root@nginx ~]# source ~/.bash_profile
[root@nginx ~]# cat ~/.bash_profile 
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs
export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/php/sbin

[root@nginx bin]# cd /data/web/php/
[root@nginx php]# vim index.php
[root@nginx php]# cat index.php
<?php
	phpinfo();
?>
[root@nginx php]# cd /usr/local/nginx/conf/
[root@nginx conf]# vim fastcgi.conf
[root@nginx nginx]# 
[root@nginx nginx]# mkdir conf.d
[root@nginx nginx]# vim conf/nginx.conf    #添加include "/usr/local/nginx/conf.d/*.conf";

[root@nginx nginx]# cd /usr/local/nginx/conf.d
[root@nginx conf.d]# vim vhost.conf
[root@nginx conf.d]# cat vhost.conf 
server {
	listen 80;
	server_name www.zx.org;
	root /data/web/html;
	index index.html;

	location ~ \.php$ {
        root /data/web/php;
		fastcgi_pass 172.25.254.110:9000;
		fastcgi_index index.php;
		include fastcgi.conf;
	}
}

 访问验证php测试页面

(5)nginx-php的缓存优化

PS C:\Users\qq358\Desktop> scp .\memcache-8.2.tgz  root@172.25.254.110:/root
[root@nginx ~]# tar zxf memcache-8.2.tgz 
[root@nginx ~]# cd memcache-8.2/
[root@nginx memcache-8.2]# dnf install autoconf -y
[root@nginx memcache-8.2]# yum install php-devel
[root@nginx memcache-8.2]# phpize
Configuring for:
PHP Api Version:         20200930
Zend Module Api No:      20200930
Zend Extension Api No:   420200930
[root@nginx memcache-8.2]# ./configure && make && make install
[root@nginx ~]# cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
[root@nginx ~]# cd /usr/local/php/etc/
[root@nginx etc]# vim php.ini 
[root@nginx etc]# systemctl restart php-fpm.service 
[root@nginx ~]# dnf install memcached.x86_64  -y    # 部署memcache
[root@nginx ~]# systemctl enable --now memcached.service
[root@nginx ~]# vim /etc/sysconfig/memcached 
[root@nginx ~]# systemctl start memcached.service 
[root@nginx lib]# cp /usr/local/php/etc/php.ini /usr/local/php/lib

#复制测试文件到nginx发布目录
[root@nginx memcache-8.2]# cp example.php memcache.php /data/web/php/
[root@nginx memcache-8.2]# cd /data/web/php/
[root@nginx php]# ls
example.php  index.php  memcache.php
[root@nginx php]# vim memcache.php     # 修改用户名和密码,访问地址

#性能对比
[root@nginx ~]# ab -n1000 -c10 http://www.zx.org/index.php

 

(6)nginx-memcache高速缓存

安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所 以nginx需要重新编译(基于以上基础)

[root@nginx memcache-8.2]# systemctl restart memcached
[root@nginx memcache-8.2]# systemctl status memcached
[root@nginx memcache-8.2]# netstat -antlupe | grep 11211
[root@nginx ~]# cd /usr/local/nginx/conf.d/
[root@nginx conf.d]# ls
vhost.conf
[root@nginx conf.d]# vim vhost.conf 
[root@nginx conf.d]# 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 conf.d]# nginx -s reload
[root@nginx conf.d]# cat vhost.conf 
upstream memcache {
	server 127.0.0.1:11211;
	keepalive 512;
}

server {
	listen 80;
	server_name www.zx.org;
	root /data/web/html;
	index index.html;
	
	location /memc {
		internal;
		memc_connect_timeout 100ms;
		memc_send_timeout 100ms;
		memc_read_timeout 100ms;
		set $mem_key $query_string;
		set $memc_exptime 300;
		memc_pass memcache;
	}
	location ~ \.php$ {
		root /data/web/php;
		set $key $uri$args;
		srcache_fetch GET /memc $key;
		srcache_store PUT /memc $key;
		fastcgi_pass 172.25.254.110:9000;
		fastcgi_index index.php;
		include fastcgi.conf;
	}
}

6、nginx二次开发版本

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方 模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

[root@nginx ~]# systemctl stop nginx
[root@nginx ~]# killall -9 nginx
[root@nginx ~]# netstat -antupe | grep nginx

PS C:\Users\qq358\Desktop> scp .\openresty-1.25.3.1.tar.gz root@172.25.254.110:/root
[root@nginx ~]# tar zxf openresty-1.25.3.1.tar.gz 
[root@nginx openresty-1.25.3.1]# dnf -y install gcc pcre-devel openssl-devel perl
[root@nginx openresty-1.25.3.1]# useradd -r -s /sbin/nologin nginx
[root@nginx ~]# cd openresty-1.25.3.1/
[root@nginx openresty-1.25.3.1]# ./configure --prefix=/usr/local/openresty \
> --with-http_realip_module \
> --with-http_sub_module \
> --with-http_gzip_static_module \
> --with-http_stub_status_module \
> --without-http_memcached_module \
> --with-stream \
> --with-stream_ssl_module \
> --with-stream_realip_module \
> --with-pcre \
> --with-http_ssl_module

[root@nginx openresty-1.25.3.1]# gmake -j2 && gmake install
[root@nginx ~]# cd /usr/local/openresty/bin
[root@nginx bin]# ll
total 168
-rwxr-xr-x 1 root root 19185 Aug 20 14:06 md2pod.pl
-rwxr-xr-x 1 root root 15994 Aug 20 14:06 nginx-xml2pod
lrwxrwxrwx 1 root root    37 Aug 20 14:06 openresty -> /usr/local/openresty/nginx/ginx
-rwxr-xr-x 1 root root 63650 Aug 20 14:06 opm
-rwxr-xr-x 1 root root 36881 Aug 20 14:06 resty
-rwxr-xr-x 1 root root 14957 Aug 20 14:06 restydoc
-rwxr-xr-x 1 root root  8873 Aug 20 14:06 restydoc-index
[root@nginx bin]# pwd
/usr/local/openresty/bin        # 将该路径写入~/.bash_profile中
[root@nginx bin]# 
[root@nginx bin]# vim ~/.bash_profile 
[root@nginx bin]# source ~/.bash_profile 
[root@nginx bin]# cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs
export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/php/sbin:/usr/local/openresty/bin

[root@nginx bin]# openresty 
[root@nginx bin]# netstat -antlupe | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      0    266529     201354/nginx: maste 
tcp        0      0 172.25.254.110:22       172.25.254.1:52801      ESTABLISHED 0    27568      1845/sshd: root [pr 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值