网站怎么推广运营,网站策划书格式及范文1000字免费,即时聊天app开发,微信指数是搜索量吗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项目#xff0c;将其打包为war8.1.1.5.启动tomcat进… 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项目将其打包为war8.1.1.5.启动tomcat进行访问测试。 8.1.2.环境准备(Nginx)8.1.2.1.使用Nginx的反向代理将请求转给Tomcat进行处理。8.1.2.2.启动访问测试 8.2.NginxTomcat来实现动静分离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,82808.3.3.启动tomcat并访问测试8.3.4.在Nginx对应的配置文件中添加如下内容: 8.4.Nginx高可用解决方案8.4.1.Keepalived8.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:从官方网站下载keepalived8.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. 分别启动两台服务器的keepalived8.4.5.6.3. 当把192.168.229.136服务器上的keepalived关闭后再次查看ip8.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-module11.1.1. LuaJIT是采用C语言编写的Lua代表的解释器11.1.2.下载lua-nginx-module11.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.干脆直接用openresty11.1.2.10.make报错修改ngx_http_lua_headers_in.c文件11.1.2.11.测试 11.2.方式二:OpenRestry11.2.1.概述11.2.2.下载OpenResty11.2.3.使用wget下载:11.2.4.解压缩:11.2.5.进入OpenResty目录:11.2.6.编译和安装11.2.7.进入OpenResty的目录找到nginx11.2.8.在conf目录下的nginx.conf添加如下内容11.2.9.在sbin目录下启动nginx11.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操作Redis13.1.介绍13.2.lua-resty-redis环境准备13.2.1.准备一个Redis环境【安装Redis】13.2.2.准备对应的API13.2.3.步骤13.2.4.效果实现13.2.5.运行测试效果 十四、ngx_lua操作Mysql14.1.介绍14.2.lua-resty-mysql14.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.引入cjson14.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_result14.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.修改某个值测试redis15.9.完整代码 endl 八、Nginx实现服务器端集群搭建
8.1.Nginx与Tomcat部署
Nginx在高并发场景和处理静态资源是非常高性能的但是在实际项目中除了静态资源还有就是后台业务代码模块一般后台业务都会被部署在Tomcatweblogic或者是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.html8.1.1.2.获取动态资源的链接地址:
http://192.168.229.131:8080/demo/getAddress8.1.1.3.在Centos上准备一个Tomcat作为后台web服务器
Tomcat官网地址https://tomcat.apache.org/下载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将tomcat进行解压缩
tar -zxf apache-tomcat-8.5.98.tar.gz8.1.1.4.准备一个web项目将其打包为war
1.将资料中的demo.war上传到tomcat8目录下的webapps包下
2.将tomcat进行启动进入tomcat8的bin目录下
./startup.sh8.1.1.5.启动tomcat进行访问测试。
静态资源: http://192.168.229.131:8080/demo/index.html
动态资源: http://192.168.229.131:8080/demo/getAddress8.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.NginxTomcat来实现动静分离
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 langen
headmeta charsetUTF-8titleTitle/titlescript srcjs/jquery.min.js/scriptscript$(function(){$.get(http://192.168.229.136/demo/getAddress,function(data){$(#msg).html(data);});});/script
/head
bodyimg srcimages/logo.png/h1Nginx如何将请求转发到后端服务器/h1h3 idmsg/h3img srcimages/mv.png/
/body
/html8.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.xml8.3.3.启动tomcat并访问测试
http://192.168.229.131:8080/demo/getAddresshttp://192.168.229.131:8180/demo/getAddresshttp://192.168.229.131:8280/demo/getAddress8.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介绍 VRRPVirtual 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成为新的Master。
Master路由有一个特权就是虚拟路由和后端服务器都是通过Master进行数据传递交互的
而备份节点则会直接丢弃这些请求和数据不做处理只是去监听Master的状态8.4.3.使用Keepalived的解决方案 8.4.4.环境搭建
8.4.4.1.环境准备
VIPIP主机名主/从192.168.229.136keepalived1Master192.168.229.222192.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.gz8.4.4.2.2.步骤2:将压缩文件进行解压缩
tar -zxf keepalived-2.0.20.tar.gz8.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 install8.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-devel8.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 -v8.4.5.Keepalived配置文件介绍 8.4.5.1.打开keepalived.conf配置文件
这里面会分三部第一部分是global全局配置、第二部分是vrrp相关配置、第三部分是LVS相关配置。 本次主要是使用keepalived实现高可用部署没有用到LVS
cd /etc/keepalived
vi /etc/keepalived/keepalived.confcd /usr/local/sbin8.4.5.2.global全局配置
global全局部分
global_defs {#通知邮件当keepalived发送切换时需要发email给具体的邮箱地址notification_email {acassenfirewall.locfailoverfirewall.locsysadminfirewall.loc}#设置发件人的邮箱信息notification_email_from Alexandre.Cassenfirewall.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 {tomitcast.cnjerryitcast.cn}notification_email_from zhaominitcast.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 {tomitcast.cnjerryitcast.cn}notification_email_from zhaominitcast.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 a8.4.5.6.2. 分别启动两台服务器的keepalived
cd /usr/local/sbin./keepalived再次通过 ip a查看ip
ip a8.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的所有它会再次成为MASTERVIP也会漂移过去然后我们再次通过浏览器访问:
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 REDIRECT8.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
numps -C nginx --no-header | wc -l # 计算nginx进程行数
if [ $num -eq 0 ];then # 判断nginx进程行数是否等于0/usr/local/nginx/sbin/nginx # 等于0启动nginxsleep 2 # 睡上2秒if [ ps -C nginx --no-header | wc -l -eq 0 ]; then # 再次判断nginx进程行数是否等于0killall keepalived # 如果报错 杀死keepalived进程fi
fiLinux ps命令用于显示当前进程 (process) 的状态。
-C(command) :指定命令的所有进程
–no-header 排除标题 8.4.6.3. 为脚本文件设置权限
chmod 755 ck_nginx.sh8.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-toolshtpasswd -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 -v11.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.gz11.1.2.2.将下载的资源进行解压:
tar -zxf lua-nginx-module-0.10.14.tar.gz11.1.2.3.更改目录名:
mv lua-nginx-module-0.10.14 lua-nginx-module11.1.2.4.导入环境变量 告诉Nginx去哪里找luajit vi /etc/profileexport LUAJIT_LIB/usr/local/lib
export LUAJIT_INC/usr/local/include/luajit-2.0source /etc/profile11.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-module11.1.2.6.安装
make make install11.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.211.1.2.8.如果启动Nginx出现以下错误信息 [rootlocalhost 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 OpenRestys; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenRestys 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.luano file /usr/local/luajit/share/luajit-2.0.5/resty/core.luano file /usr/local/share/lua/5.1/resty/core.luano file /usr/local/share/lua/5.1/resty/core/init.luano file /usr/local/luajit/share/lua/5.1/resty/core.luano file /usr/local/luajit/share/lua/5.1/resty/core/init.luano file ./resty/core.sono file /usr/local/lib/lua/5.1/resty/core.sono file /usr/local/luajit/lib/lua/5.1/resty/core.sono file /usr/local/lib/lua/5.1/loadall.sono file ./resty.sono file /usr/local/lib/lua/5.1/resty.sono file /usr/local/luajit/lib/lua/5.1/resty.sono 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 OpenRestys;
many optimizations will be disabled and performance will be compromised
(see https://github.com/openresty/luajit2 for OpenRestys 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] 错误 2vi /nginx/module/lua-nginx-module/src/ngx_http_lua_headers_in.c11.1.2.11.测试
在nginx.conf下配置如下内容:
location /lua{default_type text/html;content_by_lua ngx.say(h1HELLO,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.gz11.2.3.使用wget下载:
mkdir -p /openresty/corecd /openresty/corewget https://openresty.org/download/openresty-1.25.3.1.tar.gz11.2.4.解压缩:
tar -zxf openresty-1.25.3.1.tar.gz11.2.5.进入OpenResty目录:
cd openresty-1.25.3.111.2.6.编译和安装
./configuremake make installcd 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(h1HELLO,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 -V11.2.12.openresty安装成系统服务
# 创建脚本
vi /usr/lib/systemd/system/openresty.service# 重新加载系统服务
systemctl daemon-reload服务脚本内容
[Unit]
Descriptionopenresty web service
Documentationhttps://openresty.org/cn/
Afternetwork.target[Service]
Typeforking
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
PrivateTmptrue[Install]
WantedBydefault.target[Unit]:服务的说明
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置
Typeforking是后台运行的形式ExecStartpre是检查配置文件
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmpTrue表示给服务分配独立的临时空间
注意[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_fileinit_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张三gender1
Nginx接收到请求后根据gender传入的值如果gender传入的是1则在页面上展示
张三先生,如果gender传入的是0则在页面上展示张三女士,如果未传或者传入的不是1和2则在页面上展示张三。实现代码 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.aaabbb;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(h1HELLO,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?nameTOMgender0
http://192.168.229.136/getByGender?nameTOMgender1十三、ngx_lua操作Redis
13.1.介绍
Redis在系统中经常作为数据缓存、内存数据库使用在大型系统中扮演着非常重要的作用。 在Nginx核心系统中Redis是常备组件。 Nginx支持3种方法访问Redis,分别是HttpRedis模块、HttpRedis2Module、lua-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
port637913.2.2.准备对应的API
lua-resty-redis提供了访问Redis的详细API包括创建对接、连接、操作、数据处理等。这些API基本上与Redis的操作一一对应。
1redis require resty.redis
2new创建一个Redis对象遇到错误时redis为nilerr为错误描述信息语法: redis,err redis:new(),创建一个Redis对象。
3connect语法:ok,errredis:connect(host,port[,options_table]),设置连接Redis的连接信息。ok:连接成功返回 1连接失败返回nilerr:返回对应的错误信息
4set_timeout语法: redis:set_timeout(time) 设置请求操作Redis的超时时间。
5close语法: ok,err redis:close(),关闭当前连接成功返回1失败返回nil和错误信息
6redis命令对应的方法在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:12345614.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.数据库连接四要素:
driverClasscom.mysql.jdbc.Driver
urljdbc:mysql://192.168.200.111:3306/nginx_db
usernameroot
password12345614.4.API学习
1引入resty.mysql模块local mysql require resty.mysql
2new创建一个MySQL连接对象遇到错误时db为nilerr为错误描述信息语法: db,err mysql:new()
3connect尝试连接到一个MySQL服务器语法:ok,errdb:connect(options),options是一个参数的Lua表结构里面包含数据库连接的相关信息host:服务器主机名或IP地址port:服务器监听端口默认为3306user:登录的用户名password:登录密码database:使用的数据库名
4set_timeout设置子请求的超时时间(ms)包括connect方法语法:db:set_timeout(time)
5close关闭当前MySQL连接并返回状态。如果成功则返回1如果出现任何错误则将返回nil和错误描述。语法:db:close()
6send_query异步向远程MySQL发送一个查询。如果成功则返回成功发送的字节数如果错误则返回nil和错误描述语法:bytes,errdb:send_query(sql)
7read_result从MySQL服务器返回结果中读取一行数据。res返回一个描述OK包或结果集包的Lua表,语法:res, err, errcode, sqlstate db:read_result() res, err, errcode, sqlstate db:read_result(rows) :rows指定返回结果集的最大值默认为4如果是查询则返回一个容纳多行的数组。每行是一个数据列的key-value对如{{id1,usernameTOM,birthday1988-11-11,salary10000.0},{id2,usernameJERRY,birthday1989-11-11,salary20000.0}}如果是增删改则返回类上如下数据{insert_id 0,server_status2,warning_count1,affected_rows2,messagenil}返回值:res:操作的结果集err:错误信息errcode:MySQL的错误码比如1064sqlstate:返回由5个字符组成的标准SQL错误码比如4200014.5.步骤
-- 引入resty.mysql
-- 创建连接对象 new
-- 建立连接 传入数据库连接的相关信息
-- 判断是否连接成功
-- 设置超时时间 set_timeout
-- 发送SQL语句
-- 读取返回的结果并且把结果输出到页面
-- 关闭连接14.6.效果实现–查询单个数据
location /{content_by_lua_block{local mysql require resty.mysqllocal db mysql:new()local ok,err db:connect{host192.168.200.111,port3306,userroot,password123456,databasenginx_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/testMysql14.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)
end14.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 cjson14.9.2.调用cjson的encode方法进行类型转换
cjson.encode(res) 14.9.3.使用
location /{content_by_lua_block{local mysql require resty.mysqllocal cjson require cjsonlocal db mysql:new()local ok,err db:connect{host192.168.200.111,port3306,userroot,password123456,databasenginx_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.mysqllocal db mysql:new()local ok,err db:connect{host192.168.229.137,port3306,userroot,password123456,databasenginx_db,max_packet_size1024,compact_arraysfalse}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 usernamelisi 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 6local 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.aaabbb;charset utf-8;return 200 $param;}location /lua{default_type text/html;content_by_lua ngx.say(h1HELLO,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?usernameTOM15.3.从表中查询出符合条件的记录此时获取的结果为table类型
15.4.使用cjson将table数据转换成json字符串
15.5.将查询的结果数据存入Redis中
15.6.代码
init_by_lua_block{redis require resty.redismysql require resty.mysqlcjson 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{host192.168.200.111,port3306,userroot,password123456,databasenginx_db}if not ok thenngx.say(failed connect to mysql:,err)returnend--设置连接超时时间db:set_timeout(1000)--查询数据local sql if not param thensqlselect * from userselsesqlselect * from users where username....param..endlocal res,err,errcode,sqlstatedb: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.mysqlredis require resty.rediscjson 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{host192.168.229.137,port3306,userroot,password123456,databasenginx_db}if not ok thenngx.say(faild connect to mysql:,err)returnenddb:set_timeout(1000) --设置连接超时时间local sql --查询数据if not param thensql select * from userselsesql 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