浅谈 OpenResty,基于opebresty+redis进行实时线上限流

一.前言

我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。为了开发人员方便,所以接下来我们要介绍一种整合了Nginx和lua的框架,那就是OpenResty,它帮我们实现了可以用lua的规范开发,实现各种业务,并且帮我们弄清楚各个模块的编译顺序。关于OpenResty,我想大家应该不再陌生,随着系统架构的不断升级、优化,OpenResty在被广泛的应用。

二.OpenResty运行原理

Nginx 采用的是 master-worker 模型,一个 master 进程管理多个 worker 进程,基本的事件处理都是放在 woker 中,master 负责一些全局初始化,以及对 worker 的管理。在OpenResty中,每个 woker 使用一个 LuaVM,当请求被分配到 woker 时,将在这个 LuaVM 里创建一个 coroutine(协程)。协程之间数据隔离,每个协程具有独立的全局变量_G。

ps. 协程和多线程下的线程类似:有自己的堆栈,自己的局部变量,有自己的指令指针,但是和其他协程程序共享全局变量等信息。线程和协程的主要不同在于:多处理器的情况下,概念上来说多线程是同时运行多个线程,而协程是通过代码来完成协程的切换,任何时刻只有一个协程程序在运行。并且这个在运行的协程只有明确被要求挂起时才会被挂起。

原理图如下:

三.OpenResty的优势

首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作为一个Web Server使用。

借助于Nginx的事件驱动模型和非阻塞IO,可以实现高性能的Web应用程序。

而且OpenResty提供了大量组件如Mysql、Redis、Memcached等等,使在Nginx上开发Web应用更方便更简单。目前在京东如实时价格、秒杀、动态服务、单品页、列表页等都在使用Nginx+Lua架构,其他公司如淘宝、去哪儿网等。

四.Nginx和lua的简介

1. Nginx:

(1) Nginx的优点

  • 轻量级同样起web 服务比apache占用更少内存及资源
  • 抗并发nginx 处理请求异步非阻塞而apache 则阻塞型高并发下nginx 能保持低资源低消耗高性能
  • 高度模块化设计编写模块相对简单
  • 社区活跃各种高性能模块出品迅速啊

(2) Nginx为什么性能高,占用内存少

众所周知,nginx性能高,而nginx的高性能与其架构是分不开的。在这里,我们简单粗略的介绍一下nginx的架构。

  • 首先,nginx采用的是多多进程模式,好处是什么呢?首先,对于每个worker进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多。其次,采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快启动新的worker进程。当然,worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前worker上的所有请求失败,不过不会影响到所有请求,所以降低风险。
  • Nginx是采用异步非阻塞的方式去处理请求的,什么是异步非阻塞呢?其实就是当一个线程调用出现等待的io之类的情况时,而不是阻塞在这里,而是去处理别的事情,等io准备好了,然后再去执行,具体的我就不在这里和大家描述了。

2. lua:

(1) Lua 是一个小巧的脚本语言。作者是巴西人。该语言的设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能

(2) Lua的特点:

  • Lua脚本可以很容易的被C/C++代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,Ini等文件格式,并且更容易理解和维护。
  • Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。

五.OpenResty的安装

上面我门对OpenResty进行了简单的介绍,运行原理的说明,还有Nginx、Lua优点的介绍,是为了更好的让大家理解。让大家知道用这个的好处,接下来我简单的介绍一下OpenResty的安装和搭建一个简单的限流的例子,这是为了让大家明白,除了上面说的好处,它到底能够做什么。

OpenResty的安装:

(1) 需要事先安装一下所需的插件


1

yum install readline-devel pcre-devel openssl-devel

(2) 下载ngx_openresty-1.7.7.2.tar.gz并解压


1

wget http://openresty.org/download/ngx_openresty-1.7.7.2.tar.gz

(3) 安装LuaJIT


1

2

3

cd bundle/LuaJIT-2.1-20150120/

make clean && make && make install

ln -sf luajit-2.1.0-alpha /usr/local/bin/luajit

(4) 下载ngx_cache_purge模块,该模块用于清理nginx缓存


1

wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz

(5) 下载nginx_upstream_check_module模块,该模块用于ustream健康检查


1

wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/v0.3.0.tar.gz

(6) 安装ngx_openresty


1

2

3

4

5

6

7

8

9

cd /usr/servers/ngx_openresty-1.7.7.2

./configure

--prefix=/usr/servers

--with-http_realip_module  

--with-pcre  

--with-luajit 

--add-module=./bundle/ngx_cache_purge-2.3/ 

--add-module=./bundle/nginx_upstream_check_module-0.3.0/ -j2

make && make install

(7) 到/usr/servers目录下,会发现多出来了如下目录,说明安装成功

(8) 启动nginx:/usr/servers/nginx/sbin/nginx(其实我们可以配置好系统的环境变量,配置好后就可以直接数据nginx命令了)

六.防刷(黑白名单)简单例子的搭建

1. 首先我们先可以在/usr/servers/nginx/conf/ 目录下创建我们自己的一个简单的lua文件,就叫做example.lua好了。

输入如下命令,我们就可以创建一个example.conf文件,或者我们可以cp nginx.conf  example.conf 或者mkdir example.conf

2. 接下来我们需要编辑nginx.conf这个启动配置的文件了

ok,我们进入到编辑界面,接下来我们需要将我们的example.conf文件给引入进来,在nginx.conf的http体里添加一下命令:include example.conf

nginx.conf 的具体内容如下:

其中大家可以看到用红线框框的是自己项目文件的引入和lua模块的引入。

3. 接下来我们可以在example.conf文件中写我们的逻辑实现了

4. 我们可以看到,在example.conf中的server里面配置多个location,而location中嵌入了content_by_lua_file  /usr/example/lua/redis_black_limit.lua,从这可以看出在content阶段嵌入了lua脚本,进行了内容的响应,在这里,我们进去看看相应的代码是如何来处理的:

这是一个防刷的demo,从中我们可以看出,我是更具ip,从redis里面取值,然后通过请求ip的匹配,来做到防刷的功能,除此之外,这里有一个语句,我们的注意到,那就是require,这就相当于我们的类加载器,class.forname,从而做到加载进来lua的模块。

5. 除此之外,还简单的做了一个设置黑名单和取消黑名单的功能,用来充当我们以后的管理中心,具体逻辑写在set_black.lua和cancel.lua中,然后在lua.conf中配置好url,具体如下图所示:

在lua.conf中server体里加入一下代码:

接下来我们需要写set_black.lua和cancel.lua文件,文件内容如下:


1

2

3

4

5

6

7

8

9

10

11

12

v  set_black.lua:

local redis =require "resty.redis"

local cache =redis.new()

cache:set_timeout(6000)

local ok,err=cache.connect(cache,‘192.168.150.61‘,6379)

if not ok then

        ngx.say("failed to connect:",err)

        return

end

local ip = ngx.var.remote_addr

cache:set("user:"..ip..":block",1)

ngx.say("user:"..ip..":block".."设置黑名单成功")


1

2

3

4

5

6

7

8

9

10

11

12

v  cancel_black.lua:

local redis =require "resty.redis"

local cache =redis.new()

cache:set_timeout(6000)

local ok,err=cache.connect(cache,‘192.168.150.61‘,6379)

if not ok then

        ngx.say("failed to connect:",err)

        return

end

local ip = ngx.var.remote_addr

cache:expire("user:"..ip..":block",0)

ngx.say("user:"..ip..":block".."移除黑名单")

7. 效果

做好了以上配置,我们可以开始先设置好黑名单,然后访问请求,返回的结果是被黑名单了,然后再取消黑名单,再访问请求,显示访问成功,具体结果如下图。

七.总结

上文简单的介绍一些OpenResty,以及搭建了一个简单的应用,目的是想让大家对这个框架有一个大体的了解。随着架构的升级,我们会慢慢的把一些不太复杂的业务可以移到nginx层,从而提高我们的吞吐量,解决一些性能上的瓶颈。例如在nginx这一层做简单的限流、黑白名单,缓存之类的业务复杂性不是太强的工作,从而增加我们的吞吐率,也可以再nginx这一层过滤掉一些垃圾流量,从而让tomcat层只需要更加专注于业务。(以上是我简单粗略的一些理解,如果有什么问题,欢迎大家一起讨论)

原文地址:https://www.cnblogs.com/gxyandwmm/p/11314993.html

时间: 2024-10-13 22:38:49

浅谈 OpenResty,基于opebresty+redis进行实时线上限流的相关文章

浅谈openresty

浅谈openresty 为什么会有OpenResty? 我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏.为了开发人员方便,所以接下来我们要介绍一种整合了Nginx和lua的框架,那就是OpenResty,它帮我们实现了可以用lua的规范开发,实现各种业务,并且帮我们弄清楚各个模块的编译顺序. OpenResty(又称:ngx_openre

redis浅谈教你使用redis(一)

随着数据体积的激增,MySQL+memcache已经满足不了大型互联网类应用的需求,许多机构也纷纷选择Redis作为其架构上的补充,然而Redis的使用门槛并不低,比如不支持SQL等,这里为大家分享Redis的使用全攻略. Redis,备受关注的NoSQL数据库之一,已为众多知名互联网公司使用,比如新浪微博.Pinterest及Viacom.然而,天生不支持SQL却让他看起来很不容易接近,这里我们一起看@utopiar的博文--探索Redis. 探索之一:Redis? What is it? 简

浅谈集群版Redis和Gossip协议

今天来看一下Redis-Cluster和其中的重要概念Gossip协议. 1.Redis Cluster的基本概念 集群版的Redis听起来很高大上,确实相比单实例一主一从或者一主多从模式来说复杂了许多,互联网的架构总是随着业务的发展不断演进的. 单实例Redis架构最开始的一主N从加上读写分离,Redis作为缓存单实例貌似也还不错,并且有Sentinel哨兵机制,可以实现主从故障迁移. 单实例一主两从+读写分离结构: 单实例的由于本质上只有一台Master作为存储,就算机器为128GB的内存,

极限工坊淘小咖浅谈:实体餐饮业的变革,线上拥抱线下,小程序的新零售

随着互联网的极速发展,人们的日常生活节奏逐渐加快,实体商家的经营的商铺营业额已经到达率了瓶颈期,一些经常关注互联网的商家早已经察觉小程序这是个新的风口,而互联网的发展,也已经让实体商家不得不做起线上+线下的营业模式. 餐饮业作为实体行业的代表,即使餐品再好吃.服务再优质,也有着非常大的局限性,客户离开店面之后,就无法持续提供优质的服务.外卖和餐饮APP的出现,虽然在很大程度上处理了这个问题,但对于绝大多数中小型餐饮店主来说,他们很难像巴奴火锅.德克士这样"地主"一样的知名度,有足够的物

浅谈linux内核栈(基于3.16-rc4)

在3.16-rc4内核源码中,内核给每个进程分配的内核栈大小为8KB.这个内核栈被称为异常栈,在进程的内核空间运行时或者执行异常处理程序时,使用的都是异常栈,看下异常栈的代码(include/linux/sched.h): 1 union thread_union { 2 struct thread_info thread_info; 3 unsigned long stack[THREAD_SIZE/sizeof(long)]; 4 }; THREAD_SIZE值为8KB,因此内核为进程的异常

基于express+redis高速实现实时在线用户数统计

作者:zhanhailiang 日期:2014-11-09 本文将介绍怎样基于express+redis高速实现实时在线用户数统计. 1. 在github.com上创建项目uv-tj.将其同步到本地: [root@~/wade/nodejs]# git clone [email protected]:billfeller/uv-tj.git 2. 使用npm init初始化node项目(本例不须要复杂的操作,所以暂不使用express工具来生成express应用程序骨架): [root@~/wa

浅谈分词算法(2)基于词典的分词方法

[TOC] 前言 在浅谈分词算法(1)分词中的基本问题中我们探讨了分词中的基本问题,也提到了基于词典的分词方法.基于词典的分词方法是一种比较传统的方式,这类分词方法有很多,如:正向最大匹配(forward maximum matching method, FMM).逆向最大匹配(backward maximum matching method,BMM).双向扫描法.逐词遍历法.N-最短路径方法以及基于词的n-gram语法模型的分词方法等等.对于这类方法,词典的整理选择在其中占到了很重要的作用,本

基于swoole+Redis的消息实时推送通知

swoole+Redis将实时数据的推送 一 实现功能 设计师订单如果设计师未抢单,超时(5分钟)设计订单时时给设计师派送, 设计师公众号中收到派单信息 设计发布者收到派单成功信息 环境 centos6.10 redis-4.0.2 swoole-src-4.4.12 php-7.1.5 MYsyql5.7 在centos6默认是gcc-4.7,安装swoole的时候需要升级到gcc-4.8 二 实现流程 1.开启swoole server端监听 2.开启swoole client连接执行定时执

【架构】浅谈web网站架构演变过程

浅谈web网站架构演变过程 前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变. 该系统具备的功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架如maven+spring+struct+hibernate.maven+spri