OpenResty - 基于 NGINX 的可伸缩 Web 平台

  • 介绍

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
    页面返回值
Redis存值

四、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次


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容