8.Nginx整合OpenResty+Lua脚本
8.1.OpenResty+Lua简介
(1)OpenResty介绍
基于Nginx和Lua的高性能web平台,内部集成精良的Lua库、第三方模块、依赖,开发者可以方便搭建能够处理高并发、扩展性极高的动态web应用、web服务、动态网关。 OpenResty将Nginx核心、LuaJIT、许多有用的Lua库和Nginx第三方模块打包在一起 Nginx是c语言开发,如果要二次扩展很麻烦,而基于OpenResty,开发人员可以使用Lua编程语言对Nginx核心模块进行二次扩展 性能强大,OpenResty可以快速构造出1万以上并发连接响应的超高性能web应用系统
(2)扩展
让web服务直接泡在Nginx内部服务器,充分利用Nginx的非阻塞I/O模型,不仅仅对HTTP客户端请求,甚至对于远程后端如MYSQL、Redis等都进行一直的高性能响应。所以对于一些高性能的服务来说,可以直接使用OpenResty访问MYSQL、Redis,而不需要通过第三方语言来访问,大大提高性能
(3)Lua脚本介绍
Lua由标准的c语言编写而成,没有提供强大的库,但可以很容易的被C/C++代码调用,也可以反过来调用C/C++的函数。 在应用程序中可以被广泛应用,不过Lua是一种脚本,不适合做复杂的业务场景。 LuaJIT是采用C和汇编语言写的Lua解释器与即使编译器
(4)什么是ngx_lua
ngx_lua是Nginx的一个模块,将Lua嵌入到Nginx中,从而可以使用Lua来编写脚本,部署到Nginx中运行,即Nginx变成了一个Web容器;开发人员就可以使用Lua语言开发高新跟那个Web应用了。
(5)OpenResty提供了常用的ngx_lua开发模块
- lua-resty-memcached
- lua-resty-mysql
- lua-resty-redis
- lua-resty-dns
- lua-resty-limit-traffic
通过上述的模块,可以⽤来操作 mysql数据库、redis、memcached等,也可以⾃定义模块满⾜其他业务需求,很多经典的应⽤,⽐如开发缓存前置、数据过滤、API请求聚合、AB测试、灰度发布、降级、监控、限流、防⽕墙、⿊白名单等
(6)OpenResty安装
cd /etc/yum.repos.d/ wget https://openresty.org/package/centos/openresty.repo yum check-update yum clean all yum makecache yum install -y openresty yum -y install openresty-resty 列出所有 openresty 仓库⾥的软件包 yum --disablerepo="*" --enablerepo="openresty" list available 查看版本 resty -V
8.2.Nginx+OpenResty简单案例
(1)Nginx+OpenResty开发
编辑:/usr/local/openresty/nginx/conf/nginx.conf http{ location /{ content_by_lua_block{ ngx.say("hello lixiang;李祥"); } } }
- 启动nginx:./nginx
- curl 127.0.0.1
- 注意:如果需要指定配置⽂件 nginx -c 配置⽂件路径⽐如 ./nginx -c /usr/local/nginx/conf/nginx.conf
8.3.Nginx内置变量
Nginx内置变量
名称 | 说明 |
$arg_name | 请求中的name参数 |
$args | 请求中的参数 |
$content_length | HTTP请求信息里的“Content-Length” |
$content_type | 请求信息里的“Content-Type” |
$host | 请求信息中的Host,如果请求中没有Host行,则等于设置的服务器名 |
$hostname | 机器名使用gethostname系统调用的值 |
$host_cookie | cookie信息 |
$http_referer | 引用地址 |
$http_user_agent | 客户端代理信息 |
$http_via | 最后一个访问服务器的IP地址 |
$http_x_forwarded_for | 相当于网络访问路径 |
$is_args | 如果请求行带有参数,则返回”?“,则返回空字符串 |
$limit_rate | 对连接速率的限制 |
$nginx_version | 当前运行的nginx版本号 |
$pid | worker进程的pid |
$query_string | 与$args相同 |
$remote_port | 客户端端口号 |
$remote_addr | 客户端IP地址 |
$request_method | 请求的⽅法,⽐如"GET"、"POST"等 |
$request_uri | 请求的URI,带参数 |
$scheme | 所⽤的协议,⽐如http或者是https |
$server_name | 请求到达的服务器名 |
$server_port | 请求到达的服务器端⼝号 |
$server_protocol | 请求的协议版本,“HTTP/1.0"或"HTTP/1.1” |
$uri | 请求的URI,可能和最初的值有不同,⽐如经过重定向之类的 |
Nginx对于请求的处理分为多个阶段,从而让第三方模块通过挂在行为在不同的阶段来控制,大致如下
- 初始化阶段(Initialization Phase)
- init_by_lua_file
- init_worker_by_lua_file
- 重写与访问阶段(Rewrite/Access Phase)
- rewrite_by_lua_file
- access_by_lua_file
- 内容生成阶段(Content Phase)
- content_by_lua_file
- 日志记录阶段(Log Phase)
8.4.开发内网访问限制
- Nginx+OpenResty+Lua开发内网访问限制
- 生产环境-管理后台一般需要指定的网络才可以访问,网段/ip等
http{ #这里设置为off,为了避免每次修改之后都要重新reload的麻烦,缓存lua脚本,生产环境上设为on lua_code_cache off; #lua_package_path可以配置openrestry的文件寻址路径,$PERFIX为openrestry安装路径 #文件名使用"?"作为通配符,多个路径使用";"分割。默认的查找路径用";;" #设置纯Lua扩展库的搜寻地址 lua_package_path "$prefix/lualib/?.lua;;"; #设置c编写的Lua加班呢的搜寻地址 lua_package_cpath "$prefix/lualib/?.so;;"; server { location /{ access_by_lua_file lua/while_ip_list.lua; proxy_pass http://lbs; } } }
- 编写lua脚本
local black_ips={["127.0.0.1"]=true} local ip=ngx.var.remote_addr if true == black_ips[ip] then ngx.exit(ngx.HTTP_FORBIDDEN) return; end
- ip封禁的架构
8.5.开发资源下载限速
- Nginx+OpenResty开发资源下载限速
- 限速限流应用场景
- 下载限速:保护宽带及服务器的IO资源
- 请求限流:防止恶意攻击,保护服务器及资源安全
- 限制某个用户在一个给定时间段内能够产生的HTTP请求数
- 限流用在保护上游应用服务器不被在同一时刻的大用户量访问
- openResty下载限速案例实操
- Nginx有一个$limit_rate,这个反应的是但前请求每秒能响应的字节数,该字节数默认位配置文件中limit_rate指令的设置。
location /download/{ access_by_lua_block{ ngx.var.limit_rate = "300K" } alias /usr/local/software/; }
8.6.漏桶算法和令牌桶算法
(1)什么是漏桶算法
如果是请求限流,请求先进入到漏桶里,漏桶以固定的速度出水,也就是处理请求,当水加的过快也就是请求过多,桶会直接溢出,也就是请求被丢弃拒绝,所以漏桶算法能清醒限制数据的传输速率或请求数
(2)什么是令牌桶算法
备注:只要突发并发量不⾼于桶⾥⾯存储的令牌数据,就可以充分利⽤好机器⽹络资源。如果桶内令牌数量⼩于被消耗的量,则产⽣的令牌的速度就是均匀处理请求的速度
9.Nginx高可用LVS+Keepalived
9.1.LVS+Keepalived架构
9.2.什么是LVS
LVS是Linux Virtual Server,Linux虚拟服务器,是一个虚拟的服务器集群系统 Linux2.4内核以后,LVS已经是Linux标准内核的一部分
LVS提供了10多种调度算法:轮询、加权轮询、最小连接、目标地址散列、源地址散列等
三种负载均衡转发技术
NAT:数据进出都通过LVS,前端的Master即要对客户端发出的请求做处理,又要对后台RealServer的响应信息做处理,将RealServer响应的信息再转发给客户端,容易成为整个集群系统性能那个的瓶颈 (⽀持任意系统且可以实现端⼝映射)
DR:移花接木,最高效的负载均衡规则,前端的Master只处理客户端的请求,将请求转发给RealServer,由后台的RealServer直接响应客户端,不在经过Master,性能要优于NAT,需要LVS和RS绑定同一个VIP(⽀持多数系统,不可以实现端⼝映射)
TUNL:隧道技术,前端的Master只处理客户端的请求,将请求转发给RealServer,然后由后台的RealServer直接响应客户端,不再经过Master;(⽀持少数系统,不可以实现端⼝映射))
9.3.什么是keepalived
监控并管理LVS集群系统中各个服务节点的状态 keepalived是一个类似于交换机制的软件,核心是检测服务器的状态,如果有一台web服务器工作出现故障,keepalived将检测到并将有故障的服务器从系统中剔除,使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器集群中。 后来加入了vrrp(虚拟路由器冗余协议),除了为LVS提供高可用还可以为其他服务器如mysql等提供高可用方案
9.4.keepalived安装
#yum安装 yum -y install keepalived #配置路径 /etc/keepalived/keepalived.conf #启动命令 service keepalived start #停止命令 service keepalived stop #重启命令 service keepalived restart #查看状态 service keepalived status
- 注意:如果缺少依赖可以执行下面命令
yum install -y gcc yum install -y openssl-devel yum install -y libnl libnl-devel yum install -y libnfnetlink-devel yum install -y net-tools yum install -y vim wget
9.5.keepalived.conf核心配置
! Configuration File for keepalived global_defs { router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的 enable_script_security #允许执行外部脚本 } #配置vrrp_script,主要用于健康检查及检查失败后执行的动作。 vrrp_script chk_real_server { #健康检查脚本,当脚本返回值不为0时认为失败 script "/usr/local/software/conf/chk_server.sh" #检查频率,以下配置每2秒检查1次 interval 2 #当检查失败后,将vrrp_instance的priority减小5 weight -5 #连续监测失败3次,才认为真的健康检查失败。并调整优先级 fall 3 #连续监测2次成功,就认为成功。但不调整优先级 rise 2 user root } #配置对外提供服务的VIP vrrp_instance配置 vrrp_instance VI_1 { #指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。 state MASTER #指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP interface ens33 #相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。 virtual_router_id 51 #本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER priority 100 #心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。 advert_int 1 authentication { auth_type PASS auth_pass 1111 } #定义虚拟IP(VIP)为192.168.159.100,可多设,每行一个 virtual_ipaddress { 192.168.159.100 } #本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名 track_script { chk_real_server } } # 定义对外提供服务的LVS的VIP以及port virtual_server 192.168.159.100 80 { # 设置健康检查时间,单位是秒 delay_loop 6 # 设置负载调度的算法为rr lb_algo rr # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式 lb_kind NAT # 会话保持时间 persistence_timeout 50 #指定转发协议类型(TCP、UDP) protocol TCP # 指定real server1的IP地址 real_server 192.168.159.146 80 { # 配置节点权值,数字越大权重越高 weight 1 # 健康检查方式 TCP_CHECK { # 健康检查方式 connect_timeout 10 # 连接超时 retry 3 # 重试次数 delay_before_retry 3 # 重试间隔 connect_port 80 # 检查时连接的端口 } } }
- 配置注意
router_id后面跟的自定义的ID在同一个网络下是一致的 state后跟的MASTER和BACKUP必须大写 interface 虚拟网卡ID,只要是没有在用的IP即可 在BACKUP节点上,其keepalived.conf与Master上基本⼀致,修改state为BACKUP,priority值改⼩即可 authentication主备之间的认证⽅式,⼀般使⽤PASS即可;主备的配置必须⼀致,不能超过8位
9.6.启动keeplived验证
- 启动keeplived验证
- 当master宕机后虚拟IP就会飘逸到backup上
- 当nginx服务宕机后,但是对应的keepalived节点存活依旧可以转发过去,但是响应失败,需要配合shell脚本检测nginx服务,如果nginx服务宕机,就结束keepalived进程
- 脚本监听
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。 vrrp_script chk_real_server { #健康检查脚本,当脚本返回值不为0时认为失败 script "/usr/local/software/conf/chk_server.sh" #检查频率,以下配置每2秒检查1次 interval 2 #当检查失败后,将vrrp_instance的priority减小5 weight -5 #连续监测失败3次,才认为真的健康检查失败。并调整优先级 fall 3 #连续监测2次成功,就认为成功。但不调整优先级 rise 2 user root }
- chk_server.sh脚本内容(需要 chmod +x chk_server.sh)
#!/bin/bash #检查nginx进程是否存在 counter=$(ps -C nginx --no-heading|wc -l) if [ "${counter}" -eq "0" ]; then service keepalived stop echo 'nginx server is died.......' fi
- 常见问题
vip能ping通,vip监听的端口不通: 第一个原因:nginx1和nginx2两台服务器的服务没有正常启动 vip ping不通: 核对是否出现裂脑,常见原因为防火墙配置所致导致多播心跳失败,核对keepalived的配置是否正确
- 特别注意: 需要关闭selinux,不然sh脚本可能不生效
- getenforce 查看
- setenforce 0 关闭
10.Nginx基础架构模型剖析
- 高性能原理
- nginx通过多进程+io多路复用(epoll)实现了高并发
- 采用多个worker进程实现对cpu的利用,通过eopll对多文件描述符事件回调机制
- 拓展:linux I/O多路复⽤有select,poll,epoll