- 介绍
OpenResty封装Nginx,为Nginx提供了高性能的可扩展程序。使Nginx抗压能力得到了提升,并且提供了Lua脚本的扩展支持,将Nginx抗压能力达到10k-1000k。
OpenResty解决的是高并发。1.tomcat官方宣称的并发量是1000,厉害点的做点参数调优,也不过3000并发。2、apache的并发比tomcat更不堪,200-3003、weblogic的并发稍好,平均能达到3000左右,但是也没有达到好一个数量级。
nginx就不一样了,处理几万的请求很轻松,内存占用也不高,之前我们只是把它用作负载均衡,没想过当做一个web服务器,OpenResty的出现解决了享受nginx高并发优势的拦路虎,因为nginx是使用异步事件模型,跟传统的编程思想不一样,而lua是用c解释执行的脚本语言(执行效率很高),可以用传统的同步编程思想上,在nginx请求接进来后处理稍复杂的逻辑。
对于高并发的系统来说,都是基于内存的,或者说是基于缓存的。查询的数据都是从数据库中加载出来的,mysql 卡了,这条请求的上下文会被卡在这里。不管是 nginx 还是 apache,都会卡住这条请求,但是问题关键还在于后续的请求进来后会怎么办
apache 的做法是开启一个新的进程来处理后续的请求,但系统进程资源是有限的,所以面对大量请求时,进程耗尽,apache 就会把所有后续的请求都卡住了。
nginx 只有一个master进程和已配置个数的 worker进程,master 进程把请求交给 worker 去处理,一个worker 在可能出现阻塞的地方会注册一个事件就放过去了(epoll模型),而不是干巴巴的等待阻塞被处理完,他会继续处理后续的请求(非阻塞),当这个事件处理完之后会通过callback来通知worker继续处理那条请求后续的事情(事件驱动)因此单个worker可以处理大量请求而不会轻易让整个系统卡住。
一、Lua安装与使用
//---安装Lua相关依赖库---
yum install libtermcap-devel ncurses-devel libevent-devel readline-devel
//---安装Lua---
curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar zxvf lua-5.3.5.tar.gz
//---Lua测试---
cd lua-5.3.5
make linux test
- 编写Hello.lua脚本
//---创建lua脚本---
vi hello.lua
//---编写内容---
print("hello");
//---编写内容---
lua hello.lua
二、OpenResty安装
#添加仓库执行命令
yum install yum-utils
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
#执行安装
yum install openresy
#运行
service openresty start
#访问
http:// ip
#修改角色权限,之后可以直接加载在root下的lua脚本
vi nginx/conf/nginx.conf
三、OpenResty实现多级缓存
3.1流程
1.当用户访问地址后,先查询Nginx缓存中数据是否存在,存在则返回请求数据
2.否:查询Redis中是否存在数据。存在则将数据更新到Nginx缓存中,返回数据
3.否:查询数据库,存在则将数据更新到Redis缓存中,返回数据3.2编写Lua脚本
vi /usr/local/lua/categoryInfo.lua
ngx.header.content_type="application/json;charset=utf8"
--获取用户请求的参数,请求地址为:getCategory?category_id=1
local uri_args = ngx.req.get_uri_args();
--获取了请求参数中的category_id
local categoryId = uri_args["category_id"];
--dis_cache:加载Nginx缓存模块(需要定义
local cache_ngx = ngx.shared.dis_cache;
--根据ID 获取Nginx本地缓存数据
local contentCache = cache_ngx:get('category_cache_'..categoryId);
--判断 如果Nginx缓存无数据则从Redis中获取
if contentCache == "" or contentCache == nil then
--连接Redis获取数据
local redis = require("resty.redis");
local red = redis:new();
red:set_timeout(2000);
local ip ="IP 地址";
local port = 6379;
red:connect(ip,port);
local rescontent=red:get("categoryId_"..categoryId);
if ngx.null == rescontent then
local cjson = require("cjson");
local mysql = require("resty.mysql");
local db = mysql:new();
db:set_timeout(2000)
local props = {
host = "IP 地址",
port = 3306,
database = "category",
user = "admin",
password = "Admin123&"
}
local res = db:connect(props);
--编写sql,查询数据
local select_sql = "SELECT category_id, category_name, category_url FROM tb_category WHERE category_id ="..categoryId..";";
res = db:query(select_sql);
local responsejson = cjson.encode(res);
--数据存入Redis中
red:set("categoryId_"..categoryId,responsejson);
--输出结果
ngx.say("Mysql:"..responsejson);
db:close()
else
--数据存入Nginx中
cache_ngx:set('category_cache_'..categoryId,rescontent,5*60);
ngx.say("Redis Cache:"..rescontent);
end
red:close()
else
ngx.say("Nginx Cache:"..contentCache);
end
- 3.3 编辑nginx.conf
#Nginx配置重载
cd nginx/sbin/
./nginx -s reload
-
3.4查看结果
访问 ip:80/getCategory?category_id=1
四、Nginx限流
一般情况下,首页的并发量是比较大的,即使有了多级缓存,如果有大量恶意的请求, 也会对系统造成影响。而限流就是保护措施之一。
nginx提供两种限流的方式:
1.控制速率
2.控制并发连接数
4.1 控制速率
漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接 口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请 求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:
- 4.1.1 nginx.conf 配置
# 限流设置:配置限流的缓存空间
limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=10r/s;
$binary_remote_addr 根据请求地址进行限流
zone=myRateLimit:10m 缓存空间的名称,大小为10m
rate=10r/s 速率为每秒10次请求
-
4.1.2使用Jmeter进行测试
设置线程=10;
有部分请求失败原因是,ngingx.conf配置中,配置的速率为10r/s。平均每100ms完成一次请求,上述测试中可能存在100ms内发送了2次及以上的请求所以出现请求失败的情况。
- 4.1.3burst参数
设置一个缓冲区当有大量请求(突发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置有限,超过的请求会直接报503的错误然后返回。
#burst 设置一个大小为2的缓冲区
limit_req zone=myRateLimit burst=2;
设置线程=12;
设置线程=15;当超出burst范围的请求则处理失败。
- 4.1.4 nodelay参数:并行处理
limit_req zone=myRateLimit burst=2 nodelay;
4.2控制并发连接数
可以控制每个IP的访问量,同时控制了某个服务的访问量
-
4.2.1nginx.conf 配置
-
4.2.2使用Jmeter进行测试
设置线程=4;上述配置对单个IP访问次数最多3次