Nginx进阶篇【五】

Nginx进阶篇【五】

  • 八、Nginx实现服务器端集群搭建
    • 8.1.Nginx与Tomcat部署
      • 8.1.1.环境准备(Tomcat)
        • 8.1.1.1.浏览器访问:
        • 8.1.1.2.获取动态资源的链接地址:
        • 8.1.1.3.在Centos上准备一个Tomcat作为后台web服务器
        • 8.1.1.4.准备一个web项目,将其打包为war
        • 8.1.1.5.启动tomcat进行访问测试。
      • 8.1.2.环境准备(Nginx)
        • 8.1.2.1.使用Nginx的反向代理,将请求转给Tomcat进行处理。
        • 8.1.2.2.启动访问测试
    • 8.2.Nginx+Tomcat来实现动静分离
      • 8.2.1.动静分离概念
      • 8.2.2.需求分析
      • 8.2.3.动静分离实现步骤
        • 8.2.3.1.将demo.war项目中的静态资源都删除掉,重新打包生成一个war包,在资料中有提供。
        • 8.2.3.2.将war包部署到tomcat中,把之前部署的内容删除掉
        • 8.2.3.3.在Nginx所在服务器创建如下目录,并将对应的静态资源放入指定的位置
        • 8.2.3.4.配置Nginx的静态资源与动态资源的访问
        • 8.2.3.5.启动测试,访问http://192.168.229.136/index.html
    • 8.3.Nginx实现Tomcat集群搭建
      • 8.3.1.分析下原理与环境准备
      • 8.3.2.准备3台tomcat,使用端口进行区分[实际环境应该是三台服务器],修改server.ml,将端口修改分别修改为8080,8180,8280
      • 8.3.3.启动tomcat并访问测试,
      • 8.3.4.在Nginx对应的配置文件中添加如下内容:
    • 8.4.Nginx高可用解决方案
      • 8.4.1.Keepalived
      • 8.4.2.VRRP介绍
      • 8.4.3.使用Keepalived的解决方案
      • 8.4.4.环境搭建
        • 8.4.4.1.环境准备
        • 8.4.4.2.keepalived的安装
          • 8.4.4.2.1.步骤1:从官方网站下载keepalived
          • 8.4.4.2.2.步骤2:将压缩文件进行解压缩
          • 8.4.4.2.3.步骤3:对keepalived进行配置,编译和安装
          • 8.4.4.2.4.报错解决
        • 8.4.4.3.keepalived的系统配置文件和系统配置脚本
      • 8.4.5.Keepalived配置文件介绍
        • 8.4.5.1.打开keepalived.conf配置文件
        • 8.4.5.2.global全局配置
        • 8.4.5.3.vrrp相关配置
        • 8.4.5.4.服务器1配置内容如下:
        • 8.4.5.5.服务器2配置内容如下:
        • 8.4.5.6.访问测试
          • 8.4.5.6.1. 启动keepalived之前,咱们先使用命令 `ip a`,查看192.168.229.136和192.168.229.137这两台服务器的IP情况。
          • 8.4.5.6.2. 分别启动两台服务器的keepalived
          • 8.4.5.6.3. 当把192.168.229.136服务器上的keepalived关闭后,再次查看ip
          • 8.4.5.6.4.上面测试和Nginx有什么关系?
          • 8.4.5.6.5.解决问题:如何在服务器上让keepalived 的虚拟IP可以网络访问
          • 8.4.5.6.6.如果把192.168.229.136服务器的keepalived关闭掉,再次访问相同的地址
      • 8.4.6.Keepalived之自动切换脚本实现【keepalived之vrrp_script】
        • 8.4.6.1. 在keepalived配置文件中添加对应的配置像
        • 8.4.6.2. 编写脚本
        • 8.4.6.3. 为脚本文件设置权限
        • 8.4.6.4. 将脚本添加到
        • 8.4.6.5. 如果效果没有出来,可以使用 `tail -f /var/log/messages`查看日志信息,找对应的错误信息。
        • 8.4.6.6. 测试
        • 8.4.6.7. 模拟136Nginx服务器宕机效果测试
        • 8.4.6.8.问题思考:
  • 九、Nginx制作在线下载站点【模块ngx_http_autoindex_module】
    • 9.1.下载站点
    • 9.2.如何制作一个下载站点:
      • 9.2.1.autoindex:启用或禁用目录列表输出
      • 9.2.2.autoindex_exact_size:对应HTLM格式,指定是否在目录列表展示文件的详细大小
      • 9.2.3.autoindex_format:设置目录列表的格式
      • 9.2.4.autoindex_localtime:对应HTML格式,是否在目录列表上显示时间。
    • 9.3.资源准备
    • 9.4.Nginx配置方式如下:
    • 9.5.下载站点测试成功
  • 十、Nginx的用户认证模块【ngx_http_auth_basic_module模块】
    • 10.1.auth_basic:使用“ HTTP基本认证”协议启用用户名和密码的验证
    • 10.2.auth_basic_user_file:指定用户名和密码所在文件
    • 10.3.实现步骤:nginx.conf添加如下内容
    • 10.4.使用`htpasswd`工具生成用户名和密码
    • 10.5.测试
  • 十一、Nginx的扩展模块【ngx_lua模块环境准备】
    • 11.1.方式一:lua-nginx-module
      • 11.1.1. LuaJIT是采用C语言编写的Lua代表的解释器
      • 11.1.2.下载lua-nginx-module
        • 11.1.2.1.在centos上使用wget来下载:
        • 11.1.2.2.将下载的资源进行解压:
        • 11.1.2.3.更改目录名:
        • 11.1.2.4.导入环境变量
        • 11.1.2.5.进入Nginx的目录执行如下命令:
        • 11.1.2.6.安装
        • 11.1.2.7.如果启动Nginx出现如下错误:
        • 11.1.2.8.如果启动Nginx出现以下错误信息
        • 11.1.2.9.干脆直接用openresty
        • 11.1.2.10.make报错修改ngx_http_lua_headers_in.c文件
        • 11.1.2.11.测试
    • 11.2.方式二:OpenRestry
      • 11.2.1.概述
      • 11.2.2.下载OpenResty:
      • 11.2.3.使用wget下载:
      • 11.2.4.解压缩:
      • 11.2.5.进入OpenResty目录:
      • 11.2.6.编译和安装
      • 11.2.7.进入OpenResty的目录,找到nginx:
      • 11.2.8.在conf目录下的nginx.conf添加如下内容
      • 11.2.9.在sbin目录下启动nginx
      • 11.2.10.通过浏览器访问测试
      • 11.2.11.设置环境变量
      • 11.2.12.openresty安装成系统服务
      • 11.2.13.openresty常用命令
  • 十二、ngx_lua的使用
      • 指令执行的顺序
      • 解释下*的作用
      • init_by_lua*
      • init_worker_by_lua*
      • set_by_lua*
      • rewrite_by_lua*
      • access_by_lua*
      • content_by_lua*
      • header_filter_by_lua*
      • body_filter_by_lua*
      • log_by_lua*
      • balancer_by_lua*
      • ssl_certificate_by_*
      • 需求:
      • 实现代码
      • 测试
  • 十三、ngx_lua操作Redis
    • 13.1.介绍
    • 13.2.lua-resty-redis环境准备
      • 13.2.1.准备一个Redis环境【安装Redis】
      • 13.2.2.准备对应的API
      • 13.2.3.步骤
      • 13.2.4.效果实现
      • 13.2.5.运行测试效果
  • 十四、ngx_lua操作Mysql
    • 14.1.介绍
    • 14.2.lua-resty-mysql
    • 14.3.使用lua-resty-mysql实现数据库的查询
      • 14.3.1.准备一个Mysql环境【安装Mysql】
      • 14.3.2.创建一个数据库表及表中的数据
      • 14.3.3.数据库连接四要素:
    • 14.4.API学习
    • 14.5.步骤
    • 14.6.效果实现--查询单个数据
    • 14.7.测试
    • 14.8.查询多行数据并显示
    • 14.8.问题
    • 14.9.使用lua-cjson处理查询结果--返回JSON字符串
      • 14.9.1.引入cjson
      • 14.9.2.调用cjson的encode方法进行类型转换
      • 14.9.3.使用
      • 14.9.4.测试
      • 14.9.5.cjson定义为全局变量--防止重复代码
    • 14.10.lua-resty-mysql实现数据库的增删改
      • 14.10.1.优化send_query和read_result
      • 14.10.2.优化代码
      • 14.10.3.新增
      • 14.10.4.修改
      • 14.10.5.删除
    • 14.11.lua_mysql_redis_nginx.conf
  • 十五、综合小案例---使用ngx_lua模块完成Redis缓存预热。
    • 15.1.准备一张表(users)【上面】
    • 15.2.浏览器输入如下地址
    • 15.3.从表中查询出符合条件的记录,此时获取的结果为table类型
    • 15.4.使用cjson将table数据转换成json字符串
    • 15.5.将查询的结果数据存入Redis中
    • 15.6.代码
    • 15.7.测试结果
    • 15.8.修改某个值测试redis
    • 15.9.完整代码
  • endl

八、Nginx实现服务器端集群搭建

8.1.Nginx与Tomcat部署

Nginx在高并发场景和处理静态资源是非常高性能的,但是在实际项目中除了静态资源还有就是后台业务代码模块,一般后台业务都会被部署在Tomcat,weblogic或者是websphere等web服务器上。
那么如何使用Nginx接收用户的请求并把请求转发到后台web服务器?

在这里插入图片描述

步骤分析:

1.准备Tomcat环境,并在Tomcat上部署一个web项目
2.准备Nginx环境,使用Nginx接收请求,并把请求分发到Tomat

8.1.1.环境准备(Tomcat)

8.1.1.1.浏览器访问:
http://192.168.229.131:8080/demo/index.html

在这里插入图片描述

8.1.1.2.获取动态资源的链接地址:
http://192.168.229.131:8080/demo/getAddress

在这里插入图片描述

8.1.1.3.在Centos上准备一个Tomcat作为后台web服务器
  1. Tomcat官网地址:https://tomcat.apache.org/
  2. 下载tomcat,apache-tomcat-8.5.98.tar.gz
wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.98/bin/apache-tomcat-8.5.98.tar.gz
  1. 将tomcat进行解压缩
tar -zxf apache-tomcat-8.5.98.tar.gz

在这里插入图片描述

8.1.1.4.准备一个web项目,将其打包为war
1.将资料中的demo.war上传到tomcat8目录下的webapps包下
2.将tomcat进行启动,进入tomcat8的bin目录下
./startup.sh
8.1.1.5.启动tomcat进行访问测试。
静态资源: http://192.168.229.131:8080/demo/index.html
动态资源: http://192.168.229.131:8080/demo/getAddress

8.1.2.环境准备(Nginx)

8.1.2.1.使用Nginx的反向代理,将请求转给Tomcat进行处理。
upstream webservice {server 192.168.229.131:8080;
}
server{listen		80;server_name localhost;location /demo {proxy_pass http://webservice;}
}
user www;
worker_processes  2;events {accept_mutex on; #设置Nginx网络连接序列化,防止多个进程对连接的争抢multi_accept on; #设置Nginx的worker进程是否可以同时接收多个网络请求worker_connections 1024; # 设置Nginx单个worker进程最大的连接数use epoll; #设置Nginx使用的事件驱动模型,使用epoll函数来优化Ngin
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;tcp_nopush      on; # 主要是用来提升网络包的传输效率tcp_nodelay     on; # 提高网络包传输的实时性keepalive_timeout  65;upstream webservice {server 192.168.229.131:8080;}server {listen       80;server_name  localhost;location /demo {proxy_pass http://webservice;}location / {root   html;index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}
8.1.2.2.启动访问测试

在这里插入图片描述

8.2.Nginx+Tomcat来实现动静分离

8.2.1.动静分离概念

动静分离

  • 动:后台应用程序的业务处理

  • 静:网站的静态资源(html,javaScript,css,images等文件)

  • 分离:将两者进行分开部署访问,提供用户进行访问。举例说明就是以后所有和静态资源相关的内容都交给Nginx来部署访问,非静态内容则交个类似于Tomcat的服务器来部署访问。

为什么要动静分离?

  • Nginx在处理静态资源的时候,效率是非常高的,而且Nginx的并发访问量也是名列前茅,而Tomcat则相对比较弱一些,所以把静态资源交个Nginx后,可以减轻Tomcat服务器的访问压力并提高静态资源的访问速度。

  • 动静分离以后,降低了动态资源和静态资源的耦合度。如动态资源宕机了也不影响静态资源的展示。

如何实现动静分离?

  • 实现动静分离的方式很多,比如静态资源可以部署到CDN、Nginx等服务器上,动态资源可以部署到Tomcat,weblogic或者websphere上。

8.2.2.需求分析

在这里插入图片描述

8.2.3.动静分离实现步骤

8.2.3.1.将demo.war项目中的静态资源都删除掉,重新打包生成一个war包,在资料中有提供。
8.2.3.2.将war包部署到tomcat中,把之前部署的内容删除掉
进入到tomcat的webapps目录下,将之前的内容删除掉
将新的war包复制到webapps下
将tomcat启动

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

8.2.3.3.在Nginx所在服务器创建如下目录,并将对应的静态资源放入指定的位置

在这里插入图片描述

其中index.html页面的内容如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/jquery.min.js"></script><script>$(function(){$.get('http://192.168.229.136/demo/getAddress',function(data){$("#msg").html(data);});});</script>
</head>
<body><img src="images/logo.png"/><h1>Nginx如何将请求转发到后端服务器</h1><h3 id="msg"></h3><img src="images/mv.png"/>
</body>
</html>
8.2.3.4.配置Nginx的静态资源与动态资源的访问
upstream webservice{server 192.168.229.131:8080;
}
server {listen       80;server_name  localhost;#动态资源访问配置location /demo {proxy_pass http://webservice;}#静态资源访问配置location ~/.*\.(png|jpg|gif|js){root html/web;gzip on;}location / {root   html/web;index  index.html index.htm;}
}
8.2.3.5.启动测试,访问http://192.168.229.136/index.html

在这里插入图片描述

假如某个时间点,由于某个原因导致Tomcat后的服务器宕机了,我们再次访问Nginx,会得到如下效果,用户还是能看到页面,只是缺失了访问次数的统计,这就是前后端耦合度降低的效果,并且整个请求只和后的服务器交互了一次,js和images都直接从Nginx返回,提供了效率,降低了后的服务器的压力。

在这里插入图片描述

8.3.Nginx实现Tomcat集群搭建

在使用Nginx和Tomcat部署项目的时候,我们使用的是一台Nginx服务器和一台Tomcat服务器,效果图如下:

在这里插入图片描述

那么问题来了,如果Tomcat的真的宕机了,整个系统就会不完整,所以如何解决上述问题,一台服务器容易宕机,那就多搭建几台Tomcat服务器,这样的话就提升了后的服务器的可用性。这也就是我们常说的集群,搭建Tomcat的集群需要用到了Nginx的反向代理和赋值均衡的知识,具体如何来实现?

8.3.1.分析下原理与环境准备

在这里插入图片描述

8.3.2.准备3台tomcat,使用端口进行区分[实际环境应该是三台服务器],修改server.ml,将端口修改分别修改为8080,8180,8280

在这里插入图片描述

vim tomcat02/conf/server.xml
vim tomcat03/conf/server.xml

在这里插入图片描述
在这里插入图片描述

8.3.3.启动tomcat并访问测试,

http://192.168.229.131:8080/demo/getAddress

在这里插入图片描述

http://192.168.229.131:8180/demo/getAddress

在这里插入图片描述

http://192.168.229.131:8280/demo/getAddress

在这里插入图片描述

8.3.4.在Nginx对应的配置文件中添加如下内容:

upstream webservice{server 192.168.229.131:8080;server 192.168.229.131:8180;server 192.168.229.131:8280;
}

在这里插入图片描述
在这里插入图片描述

完成了上述环境的部署,我们已经解决了Tomcat的高可用性,一台服务器宕机,还有其他两条对外提供服务,同时也可以实现后台服务器的不间断更新。
如果是Nginx宕机了呢,那么整套系统都将服务对外提供服务了,这个如何解决?

8.4.Nginx高可用解决方案

针对于上面提到的问题,我们来分析下要想解决上述问题,需要面临哪些问题?

在这里插入图片描述

需要两台以上的Nginx服务器对外提供服务,这样的话就可以解决其中一台宕机了,另外一台还能对外提供服务,
但是如果是两台Nginx服务器的话,会有两个IP地址,用户该访问哪台服务器,用户怎么知道哪台是好的,哪台是宕机了的?

8.4.1.Keepalived

使用Keepalived来解决,Keepalived 软件由 C 编写的,最初是专为 LVS 负载均衡软件设计的,Keepalived 软件主要是通过 VRRP 协议实现高可用功能

8.4.2.VRRP介绍

在这里插入图片描述

VRRP(Virtual Route Redundancy Protocol)协议,翻译过来为虚拟路由冗余协议
VRRP协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器IP,而在路由器组内部,如果实际拥有这个对外IP的路由器如果工作正常的话就是MASTER,MASTER实现针对虚拟路由器IP的各种网络功能。其他设备不拥有该虚拟IP,状态为BACKUP,处了接收MASTER的VRRP状态通告信息以外,不执行对外的网络功能。当主机失效时,BACKUP接管原先MASTER的网络功能。

从上面的介绍信息获取到的内容就是VRRP是一种协议,那这个协议是用来干什么的?

1.选择协议

VRRP可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。
其中的虚拟路由即Virtual路由是由VRRP路由群组创建的一个不真实存在的路由,这个虚拟路由也是有对应的IP地址。
而且VRRP路由1和VRRP路由2之间会有竞争选择,通过选择会产生一个Master路由和一个Backup路由。

2.路由容错协议

Master路由和Backup路由之间会有一个心跳检测,Master会定时告知Backup自己的状态,如果在指定的时间内,
Backup没有接收到这个通知内容,Backup就会替代Master成为新的MasterMaster路由有一个特权就是虚拟路由和后端服务器都是通过Master进行数据传递交互的,
而备份节点则会直接丢弃这些请求和数据,不做处理,只是去监听Master的状态

8.4.3.使用Keepalived的解决方案

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

8.4.4.环境搭建

8.4.4.1.环境准备
VIPIP主机名主/从
192.168.229.136keepalived1Master
192.168.229.222
192.168.229.137keepalived2Backup
8.4.4.2.keepalived的安装

keepalived官网地址:https://keepalived.org/

8.4.4.2.1.步骤1:从官方网站下载keepalived
# 创建keepalived目录,方便管理资源
mkdir -p /keepalived/corecd /keepalived/corewget https://keepalived.org/software/keepalived-2.0.20.tar.gz

在这里插入图片描述

8.4.4.2.2.步骤2:将压缩文件进行解压缩
tar -zxf keepalived-2.0.20.tar.gz

在这里插入图片描述

8.4.4.2.3.步骤3:对keepalived进行配置,编译和安装
cd /keepalived/core/keepalived-2.0.20# 解决报错
yum -y install libnl libnl-devel./configure --sysconf=/etc --prefix=/usr/localmake && make install

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.4.4.2.4.报错解决

在这里插入图片描述

Use IPv4 devconf         : No
Use iptables             : Yes
Use libiptc              : No
Use libipset             : No
Use nftables             : No
init type                : systemd
Strict config checks     : No
Build genhash            : Yes
Build documentation      : No*** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.
# 解决报错
yum -y install libnl libnl-devel

在这里插入图片描述

8.4.4.3.keepalived的系统配置文件和系统配置脚本

/etc/keepalived/keepalived.conf(keepalived的系统配置文件,我们主要操作的就是该文件)
/usr/local/sbin目录下的keepalived,是系统配置脚本,用来启动和关闭keepalived

cd /etc/keepalived
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
vi /etc/keepalived/keepalived.confcd /usr/local/sbin
./keepalived -v

在这里插入图片描述
在这里插入图片描述

8.4.5.Keepalived配置文件介绍

在这里插入图片描述

8.4.5.1.打开keepalived.conf配置文件

这里面会分三部,第一部分是global全局配置、第二部分是vrrp相关配置、第三部分是LVS相关配置
本次主要是使用keepalived实现高可用部署,没有用到LVS

cd /etc/keepalived
vi /etc/keepalived/keepalived.confcd /usr/local/sbin
8.4.5.2.global全局配置
global全局部分:
global_defs {#通知邮件,当keepalived发送切换时需要发email给具体的邮箱地址notification_email {acassen@firewall.locfailover@firewall.locsysadmin@firewall.loc}#设置发件人的邮箱信息notification_email_from Alexandre.Cassen@firewall.loc#指定smpt服务地址smtp_server 192.168.229.1#指定smpt服务连接超时时间smtp_connect_timeout 30#运行keepalived服务器的一个标识,可以用作发送邮件的主题信息router_id LVS_DEVEL#默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)vrrp_skip_check_adv_addr#严格遵守VRRP协议。vrrp_strict#在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0vrrp_garp_interval 0#在一个网卡上每组na消息之间的延迟时间,默认为0vrrp_gna_interval 0
}
8.4.5.3.vrrp相关配置
VRRP部分,该部分可以包含以下四个子模块
1. vrrp_script
2. vrrp_sync_group
3. garp_group
4. vrrp_instance
我们会用到第一个和第四个,
#设置keepalived实例的相关信息,VI_1为VRRP实例名称
vrrp_instance VI_1 {state MASTER  		#有两个值可选MASTER主 BACKUP备interface ens33		#vrrp实例绑定的接口,用于发送VRRP包[当前服务器使用的网卡名称]virtual_router_id 51#指定VRRP实例ID,范围是0-255priority 100		#指定优先级,优先级高的将成为MASTERadvert_int 1		#指定发送VRRP通告的间隔,单位是秒authentication {	#vrrp之间通信的认证信息auth_type PASS	#指定认证方式。PASS简单密码认证(推荐)auth_pass 1111	#指定认证使用的密码,最多8}virtual_ipaddress { #虚拟IP地址设置虚拟IP地址,供用户访问使用,可设置多个,一行一个192.168.229.222 #指定虚拟ip,自己定义的虚拟ip}
}
8.4.5.4.服务器1配置内容如下:
global_defs {notification_email {tom@itcast.cnjerry@itcast.cn}notification_email_from zhaomin@itcast.cnsmtp_server 192.168.229.1smtp_connect_timeout 30router_id keepalived1vrrp_skip_check_adv_addrvrrp_strictvrrp_garp_interval 0vrrp_gna_interval 0
}vrrp_instance VI_1 {state MASTERinterface ens33virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.229.222}
}

在这里插入图片描述

8.4.5.5.服务器2配置内容如下:
! Configuration File for keepalivedglobal_defs {notification_email {tom@itcast.cnjerry@itcast.cn}notification_email_from zhaomin@itcast.cnsmtp_server 192.168.229.1smtp_connect_timeout 30router_id keepalived2vrrp_skip_check_adv_addrvrrp_strictvrrp_garp_interval 0vrrp_gna_interval 0
}vrrp_instance VI_1 {state BACKUPinterface ens33virtual_router_id 51priority 90advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.229.222}
}
8.4.5.6.访问测试
8.4.5.6.1. 启动keepalived之前,咱们先使用命令 ip a,查看192.168.229.136和192.168.229.137这两台服务器的IP情况。
ip a

在这里插入图片描述

在这里插入图片描述

8.4.5.6.2. 分别启动两台服务器的keepalived
cd /usr/local/sbin./keepalived

在这里插入图片描述

再次通过 ip a查看ip

ip a

在这里插入图片描述

在这里插入图片描述

8.4.5.6.3. 当把192.168.229.136服务器上的keepalived关闭后,再次查看ip
ps -ef | grep keepalived

在这里插入图片描述
在这里插入图片描述

通过上述的测试,我们会发现,虚拟IP(VIP)会在MASTER节点上当MASTER节点上的keepalived出问题以后,因为BACKUP无法收到MASTER发出的VRRP状态通过信息,就会直接升为MASTER。VIP也会"漂移"到新的MASTER

8.4.5.6.4.上面测试和Nginx有什么关系?

我们把192.168.229.136服务器的keepalived再次启动下,由于它的优先级高于服务器192.168.229.122的,所有它会再次成为MASTER,VIP也会"漂移"过去,然后我们再次通过浏览器访问:

http://192.168.229.222/

在这里插入图片描述

8.4.5.6.5.解决问题:如何在服务器上让keepalived 的虚拟IP可以网络访问

在这里插入图片描述

在宿主机上配置keepalived 启动成功后,创建虚拟IP访问不了
确保防火墙关闭还是访问不了虚拟IP 192.168.229.222

# 增加一条iptables策略,iptables对虚拟服务ip彻底放行
iptables -t nat -A PREROUTING -p tcp -d 虚拟服务ip --dport 80 -j REDIRECT 
ip asystemctl stop firewalldsystemctl status firewalldiptables -t nat -A PREROUTING -p tcp -d 192.168.229.222 --dport 80 -j REDIRECT

在这里插入图片描述
在这里插入图片描述

8.4.5.6.6.如果把192.168.229.136服务器的keepalived关闭掉,再次访问相同的地址

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

效果实现了以后, 我们会发现要想让vip进行切换,就必须要把服务器上的keepalived进行关闭,而什么时候关闭keepalived呢?应该是在keepalived所在服务器的nginx出现问题后,把keepalived关闭掉,就可以让VIP执行另外一台服务器,但是现在这所有的操作都是通过手动来完成的,我们如何能让系统自动判断当前服务器的nginx是否正确启动,如果没有,要能让VIP自动进行"漂移",这个问题该如何解决?

8.4.6.Keepalived之自动切换脚本实现【keepalived之vrrp_script】

keepalived只能做到对网络故障和keepalived本身的监控,即当出现网络故障或者keepalived本身出现问题时,进行切换。但是这些还不够,我们还需要监控keepalived所在服务器上的其他业务,比如Nginx,如果Nginx出现异常了,仅仅keepalived保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换,这个时候,我们可以通过编写脚本对业务进程进行检测监控

实现步骤:

8.4.6.1. 在keepalived配置文件中添加对应的配置像
vrrp_script 脚本名称
{script "脚本位置"interval 3 #执行时间间隔3秒weight -20 #动态调整vrrp_instance的优先级
}
8.4.6.2. 编写脚本

ck_nginx.sh

#!/bin/bash
num=`ps -C nginx --no-header | wc -l`  # 计算nginx进程行数
if [ $num -eq 0 ];then  # 判断nginx进程行数是否等于0/usr/local/nginx/sbin/nginx # 等于0启动nginxsleep 2   # 睡上2if [ `ps -C nginx --no-header | wc -l` -eq 0 ]; then   # 再次判断nginx进程行数是否等于0killall keepalived  # 如果报错 杀死keepalived进程fi
fi

Linux ps命令用于显示当前进程 (process) 的状态。

-C(command) :指定命令的所有进程

–no-header 排除标题

在这里插入图片描述

8.4.6.3. 为脚本文件设置权限
chmod 755 ck_nginx.sh

在这里插入图片描述

8.4.6.4. 将脚本添加到
vrrp_script ck_nginx {script "/etc/keepalived/ck_nginx.sh" #执行脚本的位置interval 2		#执行脚本的周期,秒为单位weight -20		#权重的计算方式
}
vrrp_instance VI_1 {state MASTERinterface ens33virtual_router_id 10priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.229.111}track_script {ck_nginx}
}

在这里插入图片描述
在这里插入图片描述

8.4.6.5. 如果效果没有出来,可以使用 tail -f /var/log/messages查看日志信息,找对应的错误信息。
8.4.6.6. 测试

在这里插入图片描述

8.4.6.7. 模拟136Nginx服务器宕机效果测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.4.6.8.问题思考:

通常如果master服务死掉后backup会变成master,但是当master服务又好了的时候 master此时会抢占VIP,这样就会发生两次切换对业务繁忙的网站来说是不好的。所以我们要在配置文件加入 nopreempt 非抢占,但是这个参数只能用于state 为backup,故我们在用HA的时候最好master 和backup的state都设置成backup 让其通过priority来竞争。

九、Nginx制作在线下载站点【模块ngx_http_autoindex_module】

9.1.下载站点

我们先来看一个网站http://nginx.org/download/这个我们刚开始学习Nginx的时候给大家看过这样的网站,该网站主要就是用来提供用户来下载相关资源的网站,就叫做下载网站
在这里插入图片描述

9.2.如何制作一个下载站点:

nginx使用的是模块ngx_http_autoindex_module来实现的,该模块处理以斜杠(“/”)结尾的请求,并生成目录列表。

nginx编译的时候会自动加载该模块,但是该模块默认是关闭的,我们需要使用下来指令来完成对应的配置

9.2.1.autoindex:启用或禁用目录列表输出

语法autoindex on|off;
默认值autoindex off;
位置http、server、location

9.2.2.autoindex_exact_size:对应HTLM格式,指定是否在目录列表展示文件的详细大小

默认为on,显示出文件的确切大小,单位是bytes。
改为off后,显示出文件的大概大小,单位是kB或者MB或者GB

语法autoindex_exact_size on|off;
默认值autoindex_exact_size on;
位置http、server、location

9.2.3.autoindex_format:设置目录列表的格式

语法autoindex_format html|xml|json|jsonp;
默认值autoindex_format html;
位置http、server、location

注意:该指令在1.7.9及以后版本中出现

9.2.4.autoindex_localtime:对应HTML格式,是否在目录列表上显示时间。

默认为off,显示的文件时间为GMT时间。
改为on后,显示的文件时间为文件的服务器时间

语法autoindex_localtime on | off;
默认值autoindex_localtime off;
位置http、server、location

9.3.资源准备

在这里插入图片描述

9.4.Nginx配置方式如下:

location /download{root /usr/local;autoindex on;autoindex_exact_size on;autoindex_format html;autoindex_localtime on;
}

XML/JSON格式[一般不用这两种方式]

9.5.下载站点测试成功

在这里插入图片描述

十、Nginx的用户认证模块【ngx_http_auth_basic_module模块】

对应系统资源的访问,我们往往需要限制谁能访问,谁不能访问。这块就是我们通常所说的认证部分,认证需要做的就是根据用户输入的用户名和密码来判定用户是否为合法用户,如果是则放行访问,如果不是则拒绝访问。

Nginx对应用户认证这块是通过ngx_http_auth_basic_module模块来实现的,它允许通过使用"HTTP基本身份验证"协议验证用户名和密码来限制对资源的访问。默认情况下nginx是已经安装了该模块,如果不需要则使用--without-http_auth_basic_module

10.1.auth_basic:使用“ HTTP基本认证”协议启用用户名和密码的验证

语法auth_basic string|off;
默认值auth_basic off;
位置http,server,location,limit_except

开启后,服务端会返回401,指定的字符串会返回到客户端,给用户以提示信息,但是不同的浏览器对内容的展示不一致。

10.2.auth_basic_user_file:指定用户名和密码所在文件

语法auth_basic_user_file file;
默认值
位置http,server,location,limit_except

指定文件路径,该文件中的用户名和密码的设置,密码需要进行加密。可以采用工具自动生成

10.3.实现步骤:nginx.conf添加如下内容

location /download{root /usr/local;autoindex on;autoindex_exact_size on;autoindex_format html;autoindex_localtime on;auth_basic 'please input your auth';auth_basic_user_file htpasswd;
}

在这里插入图片描述

10.4.使用htpasswd工具生成用户名和密码

yum install -y httpd-tools
htpasswd -c /usr/local/nginx/conf/htpasswd username //创建一个新文件记录用户名和密码
htpasswd -b /usr/local/nginx/conf/htpasswd username password //在指定文件新增一个用户名和密码
htpasswd -D /usr/local/nginx/conf/htpasswd username //从指定文件删除一个用户信息
htpasswd -v /usr/local/nginx/conf/htpasswd username //验证用户名和密码是否正确

在这里插入图片描述
在这里插入图片描述

10.5.测试

在这里插入图片描述

上述方式虽然能实现用户名和密码的验证,但是所有的用户名和密码信息都记录在文件里面,如果用户量过大的话,这种方式就显得有点麻烦,这时候我们就得通过后台业务代码来进行用户权限的校验。

十一、Nginx的扩展模块【ngx_lua模块环境准备】

Nginx是可扩展的,可用于处理各种使用场景。使用Lua扩展Nginx的功能。

ngx_lua模块概念:淘宝开发的ngx_lua模块通过将lua解释器集成进Nginx,可以采用lua脚本实现业务逻辑,由于lua的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本。

11.1.方式一:lua-nginx-module

11.1.1. LuaJIT是采用C语言编写的Lua代表的解释器

官网地址为:http://luajit.org/
git下载:https://github.com/LuaJIT/LuaJIT/tags

在官网上找到对应的下载地址:http://luajit.org/download/LuaJIT-2.0.5.tar.gz

在centos上使用wget来下载:

mkdir -p /lua/corecd /lua/corewget http://luajit.org/download/LuaJIT-2.0.5.tar.gz

在这里插入图片描述

将下载的资源进行解压:

tar -zxf LuaJIT-2.0.5.tar.gz

进入解压的目录:

cd LuaJIT-2.0.5

执行编译和安装:

make PREFIX=/usr/local/luajitmake install

在这里插入图片描述
在这里插入图片描述

测试:

luajit -v

在这里插入图片描述

11.1.2.下载lua-nginx-module

下载地址:https://github.com/openresty/lua-nginx-module/tags

11.1.2.1.在centos上使用wget来下载:
wget https://github.com/openresty/lua-nginx-module/archive/refs/tags/v0.10.14.tar.gz
11.1.2.2.将下载的资源进行解压:
tar -zxf lua-nginx-module-0.10.14.tar.gz
11.1.2.3.更改目录名:
mv lua-nginx-module-0.10.14 lua-nginx-module
11.1.2.4.导入环境变量

告诉Nginx去哪里找luajit

vi /etc/profileexport LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0source /etc/profile

在这里插入图片描述

11.1.2.5.进入Nginx的目录执行如下命令:
./configure --prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--modules-path=/usr/local/nginx/modules \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--lock-path=/usr/local/nginx/logs/nginx.lock \
--with-http_gzip_static_module \
--with-http_ssl_module \
--with-stream \
--add-module=/nginx/module/fair \
--add-module=/nginx/module/purge \
--add-module=/nginx/module/lua-nginx-module
11.1.2.6.安装
make && make install
11.1.2.7.如果启动Nginx出现如下错误:
error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory

在这里插入图片描述

解决方案:

设置软链接,使用如下命令

 ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
11.1.2.8.如果启动Nginx出现以下错误信息

在这里插入图片描述

[root@localhost sbin]# ./nginx 
nginx: [warn] lua_load_resty_core is deprecated (the lua-resty-core library is required since ngx_lua v0.10.16) in /usr/local/nginx/conf/nginx.conf:13
nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:no field package.preload['resty.core']no file './resty/core.lua'no file '/usr/local/luajit/share/luajit-2.0.5/resty/core.lua'no file '/usr/local/share/lua/5.1/resty/core.lua'no file '/usr/local/share/lua/5.1/resty/core/init.lua'no file '/usr/local/luajit/share/lua/5.1/resty/core.lua'no file '/usr/local/luajit/share/lua/5.1/resty/core/init.lua'no file './resty/core.so'no file '/usr/local/lib/lua/5.1/resty/core.so'no file '/usr/local/luajit/lib/lua/5.1/resty/core.so'no file '/usr/local/lib/lua/5.1/loadall.so'no file './resty.so'no file '/usr/local/lib/lua/5.1/resty.so'no file '/usr/local/luajit/lib/lua/5.1/resty.so'no file '/usr/local/lib/lua/5.1/loadall.so') in /usr/local/nginx/conf/nginx.conf:71

这个问题到git上面看了 ,https://github.com/openresty/lua-nginx-module/issues/1509
就是在nginx.conf 中的 http{}模块中加入下面这行代码:lua_load_resty_core off;但是检查的时候发现这命令已经废弃
在这里插入图片描述

分析原因:因为lua-nginx-module是来自openrestry,错误中提示的resty.core是openrestry的核心模块,对其下的很多函数进行了优化等工作。以前的版本默认不会把该模块编译进去,所以需要使用的话,我们得手动安装,或者禁用就可以。但是最新的lua-nginx-module模块已经强制性安装了该模块,所以此处因为缺少resty模块导致的报错信息。使用低版本lua-nginx-module-0.10.14方可解决

解决方案有两个:一种是下载对应的模块,另一种则是禁用掉restry模块,禁用的方式为:在nginx.conf http模块设置 lua_load_resty_core off来禁用

http{lua_load_resty_core off;
}
11.1.2.9.干脆直接用openresty

在这里插入图片描述

nginx: [alert] detected a LuaJIT version which is not OpenResty's; 
many optimizations will be disabled and performance will be compromised 
(see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, 
consider using the OpenResty releases from https://openresty.org/en/download.html)

让我不要用这个luajit版本,可以用openresty提供的luajit优化版本,或者干脆直接用openresty
卸载luajit官网版本,下载openresty提供的luajit优化版本

11.1.2.10.make报错修改ngx_http_lua_headers_in.c文件

‘ngx_http_headers_in_t’没有名为‘cookies’的成员
在这里插入图片描述

In file included from /usr/include/dlfcn.h:25:0,from src/os/unix/ngx_linux_config.h:58,from src/core/ngx_config.h:26,from /nginx/module/lua-nginx-module/src/ddebug.h:11,from /nginx/module/lua-nginx-module/src/ngx_http_lua_headers_in.c:10:
/nginx/module/lua-nginx-module/src/ngx_http_lua_headers_in.c:162:18: 错误:‘ngx_http_headers_in_t’没有名为‘cookies’的成员offsetof(ngx_http_headers_in_t, cookies),^
make[1]: *** [objs/addon/src/ngx_http_lua_headers_in.o] 错误 1
make[1]: 离开目录“/nginx/core/nginx-1.24.0”
make: *** [build] 错误 2
vi /nginx/module/lua-nginx-module/src/ngx_http_lua_headers_in.c

在这里插入图片描述
在这里插入图片描述

11.1.2.11.测试

在nginx.conf下配置如下内容:

location /lua{default_type 'text/html';content_by_lua 'ngx.say("<h1>HELLO,LUA</h1>")';
}

配置成功后,启动nginx,通过浏览器进行访问,如果获取到如下结果,则证明安装成功。

在这里插入图片描述

11.2.方式二:OpenRestry

11.2.1.概述

OpenResty是由淘宝工程师开发的,所以其官方网站(http://openresty.org/)我们读起来是非常的方便。OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。所以本身OpenResty内部就已经集成了Nginx和Lua,所以我们使用起来会更加方便。

11.2.2.下载OpenResty:

https://openresty.org/download/openresty-1.25.3.1.tar.gz

在这里插入图片描述

11.2.3.使用wget下载:

mkdir -p /openresty/corecd /openresty/corewget https://openresty.org/download/openresty-1.25.3.1.tar.gz

在这里插入图片描述

11.2.4.解压缩:

tar -zxf openresty-1.25.3.1.tar.gz

11.2.5.进入OpenResty目录:

cd openresty-1.25.3.1

在这里插入图片描述

11.2.6.编译和安装

./configuremake && make install
cd nginx-1.25.3
sh ./configure --prefix=/usr/local/openresty/nginx \--with-cc-opt='-O2' \--add-module=../ngx_devel_kit-0.3.3 \--add-module=../echo-nginx-module-0.63 \--add-module=../xss-nginx-module-0.06 \--add-module=../ngx_coolkit-0.2 \--add-module=../set-misc-nginx-module-0.33 \--add-module=../form-input-nginx-module-0.12 \--add-module=../encrypted-session-nginx-module-0.09 \--add-module=../srcache-nginx-module-0.33 \--add-module=../ngx_lua-0.10.26 \--add-module=../ngx_lua_upstream-0.07 \--add-module=../headers-more-nginx-module-0.37 \--add-module=../array-var-nginx-module-0.06 \--add-module=../memc-nginx-module-0.20 \--add-module=../redis2-nginx-module-0.15 \--add-module=../redis-nginx-module-0.3.9 \--add-module=../rds-json-nginx-module-0.16 \--add-module=../rds-csv-nginx-module-0.09 \--add-module=../ngx_stream_lua-0.0.14 \--with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib' \--with-stream --without-pcre2 --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_ssl_module

在这里插入图片描述

11.2.7.进入OpenResty的目录,找到nginx:

cd /usr/local/openresty/nginx/

11.2.8.在conf目录下的nginx.conf添加如下内容

location /lua{default_type 'text/html';content_by_lua 'ngx.say("<h1>HELLO,OpenRestry</h1>")';
}

在这里插入图片描述

11.2.9.在sbin目录下启动nginx

在这里插入图片描述

11.2.10.通过浏览器访问测试

在这里插入图片描述
在这里插入图片描述

11.2.11.设置环境变量

vim /etc/profile# openresty
export PATH=$PATH:/usr/local/openresty/nginx/sbin# 输入下面命令让设置的环境变量生效
source /etc/profile# 查看版本信息
nginx -V

在这里插入图片描述

在这里插入图片描述

11.2.12.openresty安装成系统服务

# 创建脚本
vi /usr/lib/systemd/system/openresty.service# 重新加载系统服务
systemctl daemon-reload

服务脚本内容

[Unit]
Description=openresty web service
Documentation=https://openresty.org/cn/
After=network.target[Service]
Type=forking
PIDFile=/usr/local/openresty/nginx/logs/nginx.pid
ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t -c /usr/local/openresty/nginx/conf/nginx.conf
ExecStart=/usr/local/openresty/nginx/sbin/nginx
ExecReload=/usr/local/openresty/nginx/sbin/nginx -s reload
ExecStop=/usr/local/openresty/nginx/sbin/nginx -s stop
PrivateTmp=true[Install]
WantedBy=default.target
[Unit]:服务的说明
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置
Type=forking是后台运行的形式ExecStartpre是检查配置文件
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmp=True表示给服务分配独立的临时空间
注意:[Service]的启动、重启、停止命令全部要求使用绝对路径
[Install]运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为3

11.2.13.openresty常用命令

# 启动服务
systemctl start openresty#停止
systemctl stop openresty#重启
systemctl restart openresty#重新加载配置文件
systemctl reload openresty# 查看nginx状态
systemctl status openresty# 开机启动
systemctl enable openresty.service# 查看nginx是否启动
ps -ef | grep openresty

在这里插入图片描述

十二、ngx_lua的使用

指令执行的顺序

使用Lua编写Nginx脚本的基本构建块是指令。指令用于指定何时运行用户Lua代码以及如何使用结果。下图显示了执行指令的顺序

在这里插入图片描述

解释下*的作用

*:无 , 即 xxx_by_lua ,指令后面跟的是 lua指令
*:_file,即 xxx_by_lua_file 指令后面跟的是 lua文件
*:_block,即 xxx_by_lua_block 在0.9.17版后替换init_by_lua_file

init_by_lua*

该指令在每次Nginx重新加载配置时执行,可以用来完成一些耗时模块的加载,或者初始化一些全局配置。

init_worker_by_lua*

该指令用于启动一些定时任务,如心跳检查、定时拉取服务器配置等。

set_by_lua*

该指令只要用来做变量赋值,这个指令一次只能返回一个值,并将结果赋值给Nginx中指定的变量。

rewrite_by_lua*

该指令用于执行内部URL重写或者外部重定向,典型的如伪静态化URL重写,本阶段在rewrite处理阶段的最后默认执行。

access_by_lua*

该指令用于访问控制。例如,如果只允许内网IP访问。

content_by_lua*

该指令是应用最多的指令,大部分任务是在这个阶段完成的,其他的过程往往为这个阶段准备数据,正式处理基本都在本阶段。

header_filter_by_lua*

该指令用于设置应答消息的头部信息。

body_filter_by_lua*

该指令是对响应数据进行过滤,如截断、替换。

log_by_lua*

该指令用于在log请求处理阶段,用Lua代码处理日志,但并不替换原有log处理。

balancer_by_lua*

该指令主要的作用是用来实现上游服务器的负载均衡器算法

ssl_certificate_by_*

该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码。

需求:

http://192.168.229.136?name=张三&gender=1
Nginx接收到请求后,根据gender传入的值,如果gender传入的是1,则在页面上展示
张三先生,如果gender传入的是0,则在页面上展示张三女士,如果未传或者传入的不是12则在页面上展示张三。

实现代码

        location /getByGender {default_type 'text/html';#set_by_luaset_by_lua $param "-- 获取请求url上的参数对应值 name genderlocal uri_args = ngx.req.get_uri_args()local name = uri_args['name']local gender = uri_args['gender']-- 条件判断 if gender 1 先生 0 女生if gender == '1' thenreturn name..'先生'elseif gender == '0' thenreturn name..'女士'elsereturn nameend";header_filter_by_lua "ngx.header.aaa='bbb'";charset utf-8;return 200 $param;}

在这里插入图片描述

worker_processes  1;
events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;server {listen       80;server_name  localhost;location /getByGender {default_type 'text/html';#set_by_luaset_by_lua $param "-- 获取请求url上的参数对应值 name genderlocal uri_args = ngx.req.get_uri_args()local name = uri_args['name']local gender = uri_args['gender']-- 条件判断 if gender 1 先生 0 女生if gender == '1' thenreturn name..'先生'elseif gender == '0' thenreturn name..'女士'elsereturn nameend";charset utf-8;return 200 $param;}location /lua{default_type 'text/html';content_by_lua 'ngx.say("<h1>HELLO,OpenRestry</h1>")';}location / {root   html;index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}

测试

http://192.168.229.136/getByGender?name=TOM&gender=0
http://192.168.229.136/getByGender?name=TOM&gender=1

在这里插入图片描述
在这里插入图片描述

十三、ngx_lua操作Redis

13.1.介绍

Redis在系统中经常作为数据缓存内存数据库使用,在大型系统中扮演着非常重要的作用。
在Nginx核心系统中,Redis是常备组件。
Nginx支持3种方法访问Redis,分别是HttpRedis模块HttpRedis2Modulelua-resty-redis库
这三种方式中HttpRedis模块提供的指令少,功能单一,适合做简单缓存,
HttpRedis2Module模块比HttpRedis模块操作更灵活,功能更强大。
Lua-resty-redis库OpenResty提供的一个操作Redis的接口库,可根据自己的业务情况做一些逻辑处理,适合做复杂的业务逻辑。

13.2.lua-resty-redis环境准备

13.2.1.准备一个Redis环境【安装Redis】

连接地址
host= 192.168.229.137
port=6379

在这里插入图片描述

13.2.2.准备对应的API

lua-resty-redis提供了访问Redis的详细API,包括创建对接、连接、操作、数据处理等。这些API基本上与Redis的操作一一对应。
(1)redis = require "resty.redis"2new创建一个Redis对象,遇到错误时,redis为nil,err为错误描述信息语法: redis,err = redis:new(),创建一个Redis对象。
(3)connect语法:ok,err=redis:connect(host,port[,options_table]),设置连接Redis的连接信息。ok:连接成功返回 1,连接失败返回nilerr:返回对应的错误信息
(4)set_timeout语法: redis:set_timeout(time) ,设置请求操作Redis的超时时间。
(5)close语法: ok,err = redis:close(),关闭当前连接,成功返回1,失败返回nil和错误信息
(6)redis命令对应的方法在lua-resty-redis中,所有的Redis命令都有自己的方法,方法名字和命令名字相同,只是全部为小写。

13.2.3.步骤

-- 引入Redis对应的接口对象
-- 创建一个Redis对象
-- 设置超时时间
-- 获取连接
--Redis中存储数据
--Redis中获取数据
-- 关闭连接

13.2.4.效果实现

location / {default_type "text/html";content_by_lua_block{local redis = require "resty.redis" -- 引入Redis对应的接口对象local redisObj = redis:new()  -- 创建一个Redis对象redisObj:set_timeout(1000) -- 设置超时时间1slocal ok,err = redisObj:connect("192.168.229.137",6379) -- 设置redis连接信息if not ok then -- 判断是否连接成功ngx.say("failed to connection redis",err)returnendok,err = redisObj:set("username","TOM")--Redis中存储数据if not ok then -- 判断是否存入成功ngx.say("failed to set username",err)returnendlocal res,err = redisObj:get("username") -- 从redis中获取数据ngx.say(res)	-- 将数据写会消息体中redisObj:close()  -- 关闭连接}
}

在这里插入图片描述

13.2.5.运行测试效果

http://192.168.229.136/testRedis

在这里插入图片描述

十四、ngx_lua操作Mysql

14.1.介绍

MySQL是一个使用广泛的关系型数据库。在ngx_lua中,MySQL有两种访问模式,分别是使

(1)用ngx_lua模块和lua-resty-mysql模块:这两个模块是安装OpenResty时默认安装的。

(2)使用drizzle_nginx_module(HttpDrizzleModule)模块:需要单独安装,这个库现不在OpenResty中。

14.2.lua-resty-mysql

lua-resty-mysql是OpenResty开发的模块,使用灵活、功能强大,适合复杂的业务场景,同时支持存储过程的访问。

14.3.使用lua-resty-mysql实现数据库的查询

14.3.1.准备一个Mysql环境【安装Mysql】

host: 192.168.229.137
port: 3306
username:root
password:123456

在这里插入图片描述

14.3.2.创建一个数据库表及表中的数据

create database nginx_db;use nginx_db;create table users(id int primary key auto_increment,username varchar(30),birthday date,salary double
);insert into users(id,username,birthday,salary) values(null,"TOM","1988-11-11",10000.0);
insert into users(id,username,birthday,salary) values(null,"JERRY","1989-11-11",20000.0);
insert into users(id,username,birthday,salary) values(null,"ROWS","1990-11-11",30000.0);
insert into users(id,username,birthday,salary) values(null,"LUCY","1991-11-11",40000.0);
insert into users(id,username,birthday,salary) values(null,"JACK","1992-11-11",50000.0);

在这里插入图片描述
在这里插入图片描述

14.3.3.数据库连接四要素:

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.200.111:3306/nginx_db
username=root
password=123456

14.4.API学习

1)引入"resty.mysql"模块local mysql = require "resty.mysql"2new创建一个MySQL连接对象,遇到错误时,db为nil,err为错误描述信息语法: db,err = mysql:new()3)connect尝试连接到一个MySQL服务器语法:ok,err=db:connect(options),options是一个参数的Lua表结构,里面包含数据库连接的相关信息host:服务器主机名或IP地址port:服务器监听端口,默认为3306user:登录的用户名password:登录密码database:使用的数据库名
(4)set_timeout设置子请求的超时时间(ms),包括connect方法语法:db:set_timeout(time)5)close关闭当前MySQL连接并返回状态。如果成功,则返回1;如果出现任何错误,则将返回nil和错误描述。语法:db:close()6)send_query异步向远程MySQL发送一个查询。如果成功则返回成功发送的字节数;如果错误,则返回nil和错误描述语法:bytes,err=db:send_query(sql)7)read_result从MySQL服务器返回结果中读取一行数据。res返回一个描述OK包或结果集包的Lua,语法:res, err, errcode, sqlstate = db:read_result() res, err, errcode, sqlstate = db:read_result(rows) :rows指定返回结果集的最大值,默认为4如果是查询,则返回一个容纳多行的数组。每行是一个数据列的key-value对,如{{id=1,username="TOM",birthday="1988-11-11",salary=10000.0},{id=2,username="JERRY",birthday="1989-11-11",salary=20000.0}}如果是增删改,则返回类上如下数据{insert_id = 0,server_status=2,warning_count=1,affected_rows=2,message=nil}返回值:res:操作的结果集err:错误信息errcode:MySQL的错误码,比如1064sqlstate:返回由5个字符组成的标准SQL错误码,比如42000

14.5.步骤

-- 引入resty.mysql
-- 创建连接对象 new
-- 建立连接 传入数据库连接的相关信息
-- 判断是否连接成功
-- 设置超时时间 set_timeout
-- 发送SQL语句
-- 读取返回的结果,并且把结果输出到页面
-- 关闭连接

14.6.效果实现–查询单个数据

location /{content_by_lua_block{local mysql = require "resty.mysql"local db = mysql:new()local ok,err = db:connect{host="192.168.200.111",port=3306,user="root",password="123456",database="nginx_db"}db:set_timeout(1000)db:send_query("select * from users where id =1")local res,err,errcode,sqlstate = db:read_result()ngx.say(res[1].id..","..res[1].username..","..res[1].birthday..","..res[1].salary)db:close()}}

在这里插入图片描述

14.7.测试

http://192.168.229.136/testMysql

在这里插入图片描述

14.8.查询多行数据并显示

db:send_query("select * from users")
-- 读取返回的结果,并且把结果输出到页面
local res,err,errcode,sqlstate = db:read_result()for i,v in ipairs(res) dongx.say(v.id..","..v.username..","..v.birthday..","..v.salary.."<br>")
end

在这里插入图片描述

在这里插入图片描述

14.8.问题

1.如何获取返回数据的内容
2.如何实现查询多条数据
3.如何实现数据库的增删改操作

14.9.使用lua-cjson处理查询结果–返回JSON字符串

read_result()得到的结果res都是table类型,要想在页面上展示,就必须知道table的具体数据结构才能进行遍历获取。处理起来比较麻烦,接下来我们介绍一种简单方式cjson,使用它就可以将table类型的数据转换成json字符串,把json字符串展示在页面上即可。具体如何使用?

14.9.1.引入cjson

local cjson = require "cjson"

14.9.2.调用cjson的encode方法进行类型转换

cjson.encode(res) 

14.9.3.使用

location /{content_by_lua_block{local mysql = require "resty.mysql"local cjson = require "cjson"local db = mysql:new()local ok,err = db:connect{host="192.168.200.111",port=3306,user="root",password="123456",database="nginx_db"}db:set_timeout(1000)db:send_query("select * from users")local res,err,errcode,sqlstate = db:read_result()ngx.say(cjson.encode(res))db:close()}}

在这里插入图片描述

14.9.4.测试

在这里插入图片描述

14.9.5.cjson定义为全局变量–防止重复代码

    init_by_lua_block{cjson = require "cjson" -- 引入cjson}server {listen       80;server_name  localhost;location /testMysql {default_type "text/html";content_by_lua_block{-- 引入cjson-- local cjson = require "cjson"-- 引入resty.mysqllocal mysql = require "resty.mysql"-- 创建连接对象 newlocal db = mysql:new()-- 建立连接 传入数据库连接的相关信息local ok,err = db:connect{host = "192.168.229.137",port = 3306,user = "root",password = "123456",database = "nginx_db"}if not ok then -- 判断是否连接成功ngx.say("faild to connect mysql",err)returnend-- 设置超时时间 set_timeoutdb:set_timeout(1000)-- 发送SQL语句db:send_query("select * from users")-- 读取返回的结果,并且把结果输出到页面local res,err,errcode,sqlstate = db:read_result()-- ngx.say(res[1].id..","..res[1].username..","..res[1].birthday..","..res[1].salary)--[[for i,v in ipairs(res) dongx.say(v.id..","..v.username..","..v.birthday..","..v.salary.."<br>")end--]]ngx.say(cjson.encode(res))-- 关闭连接db:close()}}

在这里插入图片描述
在这里插入图片描述

14.10.lua-resty-mysql实现数据库的增删改

14.10.1.优化send_query和read_result

本方法是send_query和read_result组合的快捷方法。

语法:

res, err, errcode, sqlstate = db:query(sql[,rows])

14.10.2.优化代码

location /{content_by_lua_block{local mysql = require "resty.mysql"local db = mysql:new()local ok,err = db:connect{host="192.168.229.137",port=3306,user="root",password="123456",database="nginx_db",max_packet_size=1024,compact_arrays=false}db:set_timeout(1000)local res,err,errcode,sqlstate = db:query("select * from users")--local res,err,errcode,sqlstate = db:query("insert into users(id,username,birthday,salary) values(null,'zhangsan','2020-11-11',32222.0)")--local res,err,errcode,sqlstate = db:query("update users set username='lisi' where id = 6")--local res,err,errcode,sqlstate = db:query("delete from users where id = 6")db:close()}
}

在这里插入图片描述

14.10.3.新增

在这里插入图片描述
在这里插入图片描述

14.10.4.修改

在这里插入图片描述
在这里插入图片描述

14.10.5.删除

在这里插入图片描述
在这里插入图片描述

14.11.lua_mysql_redis_nginx.conf

worker_processes  1;
events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;init_by_lua_block{cjson = require "cjson" -- 引入cjson}server {listen       80;server_name  localhost;location /testMysql {default_type "text/html";content_by_lua_block{-- 引入cjson-- local cjson = require "cjson"-- 引入resty.mysqllocal mysql = require "resty.mysql"-- 创建连接对象 newlocal db = mysql:new()-- 建立连接 传入数据库连接的相关信息local ok,err = db:connect{host = "192.168.229.137",port = 3306,user = "root",password = "123456",database = "nginx_db"}if not ok then -- 判断是否连接成功ngx.say("faild to connect mysql",err)returnend-- 设置超时时间 set_timeoutdb:set_timeout(1000)-- 发送SQL语句-- db:send_query("select * from users")-- 读取返回的结果,并且把结果输出到页面-- local res,err,errcode,sqlstate = db:read_result()-- 查询-- local sql = "select * from users"-- 新增-- local sql = "insert into users(username,birthday,salary) values ('zhangsan','2024-12-12',3334)"-- 修改-- local sql = "update users set username = 'lisi' where id = 6"-- 删除local sql = "delete from users where id = 6"local res,err,errcode,sqlstate = db:query(sql)-- ngx.say(res[1].id..","..res[1].username..","..res[1].birthday..","..res[1].salary)--[[for i,v in ipairs(res) dongx.say(v.id..","..v.username..","..v.birthday..","..v.salary.."<br>")end--]]ngx.say(cjson.encode(res))-- 关闭连接db:close()}}location /testRedis {default_type "text/html";content_by_lua_block{-- 引入Redis对应的接口对象local redis = require "resty.redis"-- 创建一个Redis对象local redisObj = redis:new()-- 设置超时时间redisObj:set_timeout(1000)-- 获取连接local ok,err = redisObj:connect("192.168.229.137",6379)if not ok thenngx.say("faild to connect redis",err)returnend--Redis中存储数据ok,err = redisObj:set("username","ROSE")if not ok thenngx.say("faild to connect username",err)returnend--Redis中获取数据local res,err = redisObj:get("username")ngx.say(res)-- 关闭连接redisObj:close()}}location /getByGender {default_type 'text/html';#set_by_luaset_by_lua $param "-- 获取请求url上的参数对应值 name genderlocal uri_args = ngx.req.get_uri_args()local name = uri_args['name']local gender = uri_args['gender']-- 条件判断 if gender 1 先生 0 女生if gender == '1' thenreturn name..'先生'elseif gender == '0' thenreturn name..'女士'elsereturn nameend";header_filter_by_lua "ngx.header.aaa='bbb'";charset utf-8;return 200 $param;}location /lua{default_type 'text/html';content_by_lua 'ngx.say("<h1>HELLO,OpenRestry</h1>")';}location / {root   html;index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}

十五、综合小案例—使用ngx_lua模块完成Redis缓存预热。

15.1.准备一张表(users)【上面】

15.2.浏览器输入如下地址

http://191.168.229.137?username=TOM

15.3.从表中查询出符合条件的记录,此时获取的结果为table类型

15.4.使用cjson将table数据转换成json字符串

15.5.将查询的结果数据存入Redis中

15.6.代码

init_by_lua_block{redis = require "resty.redis"mysql = require "resty.mysql"cjson = require "cjson"
}
location /{default_type "text/html";content_by_lua_block{--获取请求的参数usernamelocal param = ngx.req.get_uri_args()["username"]--建立mysql数据库的连接local db = mysql:new()local ok,err = db:connect{host="192.168.200.111",port=3306,user="root",password="123456",database="nginx_db"}if not ok thenngx.say("failed connect to mysql:",err)returnend--设置连接超时时间db:set_timeout(1000)--查询数据local sql = ""if not param thensql="select * from users"elsesql="select * from users where username=".."'"..param.."'"endlocal res,err,errcode,sqlstate=db:query(sql)if not res thenngx.say("failed to query from mysql:",err)returnend--连接redislocal rd = redis:new()ok,err = rd:connect("192.168.200.111",6379)if not ok thenngx.say("failed to connect to redis:",err)returnendrd:set_timeout(1000)--循环遍历数据for i,v in ipairs(res) dord:set("user_"..v.username,cjson.encode(v))endngx.say("success")rd:close()db:close()}}

15.7.测试结果

在这里插入图片描述

15.8.修改某个值测试redis

在这里插入图片描述
在这里插入图片描述

15.9.完整代码

worker_processes  1;
events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;init_by_lua_block{mysql = require "resty.mysql"redis = require "resty.redis"cjson = require "cjson"}server {listen       80;server_name  localhost;location / {default_type "text/html";content_by_lua_block{-- 获取传入的参数local param = ngx.req.get_uri_args()["username"] -- 获取请求的参数username-- 建立mysql数据库的连接local db = mysql:new()local ok,err = db:connect{host="192.168.229.137",port=3306,user="root",password="123456",database="nginx_db"}if not ok thenngx.say("faild connect to mysql:",err)returnenddb:set_timeout(1000) --设置连接超时时间local sql = "" --查询数据if not param thensql = "select * from users"elsesql = "select * from users where username =".."'"..param.."'"endlocal res,err,errcode,sqlstate = db:query(sql)if not res thenngx.say("faild to query from mysql:",err)returnend-- 连接redislocal rd = redis:new()ok,err = rd:connect("192.168.229.137",6379)if not ok thenngx.say("faild connect to redis:",err)returnendrd:set_timeout(1000)for i,v in ipairs(res) dord:set("user_"..v.username,cjson.encode(v))  -- cjson转换为JSON字符串存储到redisendngx.say("success")rd:close()db:close()}}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}

endl

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/652344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于GPT3.5逆向 和 本地Bert-Vits2-2.3 的语音智能助手

文章目录 一、效果演示二、操作步骤三、架构解析 一、效果演示 各位读者你们好&#xff0c;我最近在研究一个语音助手的项目&#xff0c;是基于GPT3.5网页版的逆向和本地BertVits2-2.3 文字转语音&#xff0c;能实现的事情感觉还挺多&#xff0c;目前实现【无需翻墙&#xff0…

ubuntu20.04 安装ROS2 记录

主要参考B站古月居的ROS2入门21讲 和 以下链接&#xff08;基本和视频上一致&#xff09; ubuntu20.04安装ROS2 详细教程_ubuntu20.04 ros2-CSDN博客 但是中间有些需要注意的地方&#xff0c; 1&#xff0c;添加源 步骤中提到 sudo curl -sSL https://raw.githubuserconten…

LaTeX基础使用【系列四】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;LaTeX基础使用 &#x1f984;1 LaTeX的多行数学公式&#x1f420;1.1 导入包&#x1f420;1.2 gather环境&#xff1a;多行公式&#x1f420;1.3 gather\* &#xff1a;无编号公式&#x1…

Codeforces Round 921 (Div. 2)

A. We Got Everything Covered! 题意&#xff1a;有任意由前k个字母组成的长度为n的字符串s1&#xff0c;你需要构建一个字符串s2&#xff0c;使s1恒为s2的子串&#xff08;注意是子串&#xff0c;不是连续子串&#xff09; 分析&#xff1a;我们可以构造n组字符串&#xff0c…

深入Pyecharts:桑基图绘制与炫酷效果实战【第38篇—python:桑基图】

文章目录 深入Pyecharts&#xff1a;桑基图绘制与炫酷效果实战桑基图简介安装 Pyecharts简单桑基图的绘制自定义桑基图的炫酷效果高级样式定制 多组数据桑基图的展示动态桑基图的绘制结合真实数据的桑基图案例导出和分享进阶应用&#xff1a;桑基图与其他图表的组合总结 深入Py…

Ps:渐变编辑器

渐变编辑器 Gradient Editor可用于创建和编辑自定义渐变&#xff0c;它提供了详细的控制选项&#xff0c;能够精确地调整渐变的颜色、样式和效果。 提示&#xff1a; 拖动边框或边角可缩放渐变编辑器窗口。 预设 Presets 提供了大量的渐变预设。还可通过右侧按钮新建 New、导入…

python在线聊天室(带聊天保存)

python Socket在线聊天室(带聊天保存) 需求功能 1.聊天信息保存功能(服务端会把信息保存到一个txt里面) 2.使用pyqt5框架作为一个可视化界面 3.具备一个服务端和多个客户端的功能 4.具备离线加入黑名单(离线踢出) 5.具备在线加入黑名单(在线加入黑名单被踢出) 6.具备群聊功能…

什么是网络?

你是一台电脑&#xff0c;你的名字叫 A 很久很久之前&#xff0c;你不与任何其他电脑相连接&#xff0c;孤苦伶仃。 直到有一天&#xff0c;你希望与另一台电脑 B 建立通信&#xff0c;于是你们各开了一个网口&#xff0c;用一根网线连接了起来。 用一根网线连接起来怎么就能&…

【大数据】Flink 架构(一):系统架构

Flink 架构&#xff08;一&#xff09;&#xff1a;系统架构 1.Flink 组件1.1 JobManager1.2 ResourceManager1.3 TaskManager1.4 Dispatcher 2.应用部署2.1 框架模式2.2 库模式 3.任务执行4.高可用设置4.1 TaskManager 故障4.2 JobManager 故障 Flink 是一个用于状态化并行流处…

第九篇【传奇开心果系列】beeware的toga开发移动应用示例:人口普查手机应用

传奇开心果博文系列 系列博文目录beeware的toga开发移动应用示例系列博文目录一、项目目标二、安装依赖三、实现应用雏形示例代码四、扩展功能和组件的考量五、添加更多输入字段示例代码六、添加验证功能示例代码七、添加数据存储功能示例代码八、添加数据展示功能示例代码九、…

JavaWeb,Vue的学习(上)

概述 Vue的两个核心功能 声明式渲染&#xff1a;Vue 基于标准 HTML 拓展了一套模板语法&#xff0c;使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。响应性&#xff1a;Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM ViteVue3项目…

Image Enhancement Guided Object Detection in Visually Degraded Scenes

Abstract 目标检测准确率在视觉退化场景下降严重。一个普遍的解决方法就是对退化图像进行增强然后再执行目标检测。但是&#xff0c;这是一种次优的方案&#xff0c;而且未必对目标检测的准确率有提升&#xff0c;因为图像增强和目标检测两个任务的不同。为了解决这个问题&…

elasticsearch8.x版本docker部署说明

前提&#xff0c;当前部署没有涉及证书和https访问 1、环境说明,我采用三个节点&#xff0c;每个节点启动两个es&#xff0c;用端口区分 主机角色ip和端口服务器Amaster192.168.2.223:9200服务器Adata192.168.2.223:9201服务器Bdata,master192.168.2.224:9200服务器Bdata192.1…

5_机械臂运动学基础_矩阵

上次说的向量空间是为矩阵服务的。 1、学科回顾 从科技实践中来的数学问题无非分为两类&#xff1a;一类是线性问题&#xff0c;一类是非线性问题。线性问题是研究最久、理论最完善的&#xff1b;而非线性问题则可以在一定基础上转化为线性问题求解。 线性变换&#xff1a; 数域…

【代码随想录-数组】螺旋矩阵 II

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

设计模式:简介及基本原则

简介 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式于己于他人于系统都是多赢的&#xff0c;设计模式使代码编制真正工程化&#xff…

Jenkins邮件推送配置

目录 涉及Jenkins插件&#xff1a; 邮箱配置 什么是授权码 在第三方客户端/服务怎么设置 IMAP/SMTP 设置方法 POP3/SMTP 设置方法 获取授权码&#xff1a; Jenkins配置 从Jenkins主面板System configuration>System进入邮箱配置 在Email Extension Plugin 邮箱插件…

docker compose实现mysql一主多从

参考了很多博客&#xff0c;死磕了几天&#xff0c;最终跑起来了&#xff0c;不容易&#xff0c;晚上喝瓶82年可乐庆祝下。 1、整体文件结构&#xff0c;这里忽略log、conf、data映射目录 2、docker-compose.yml文件内容如下&#xff1a; version: 3.3 services:mysql-master…

Linux中断 -- 中断路由、优先级、数据和标识

目录 1.中断路由 2.中断优先级 3.中断平衡 4.Linux内核中重要的数据结构 5.中断标识 承前文&#xff0c;本文从中断路由、优先级、数据结构和标识意义等方面对Linux内核中断进行一步的解析。 1.中断路由 Aset affinity flow GIC文中有提到SPI类型中断的路由控制器寄存器为…

华为HCIP Datacom H12-831 卷14

多选题 1、以下哪些Community属性可以保证BGP路由条目的传播范围只在AS内? A No_Export B No_Export_Subconfed C Interne D No_Advertise 正确答案 A,B 解析&#xff1a;Internet&#xff1a;缺省情况下&#xff0c;所有的路由都属于internet团体。具有此属性的路由…