为什么80%的码农都做不了架构师?>>>   

1、命令简介

http{

limit_req_zone  $binary_remote_addr  zone=one:10m   rate=1r/s;

server {

location /{

limit_req   zone=one  burst=5  nodelay;

}

}

}

limit_req_zone

语法:limit_req_zone  $session_variable  zone=name:size  rate=rate

默认值:none

上下文:http

命令解析:为session会话状态分配一个大小为size的内存存储区,限制了每秒(分、小时)只接受rate个IP的频率。

limit_req

语法:limit_req  zone=name  burst=burst  [nodelay]

默认值:none

上下文:http、server、location

命令解析:该指令用于指定使用的内存存储区(zone)名称,以及最大的突发请求数(burse)。如果请求的速率超过了limit_req_zone指令中设置的速率,这些请求将被延迟处理,在这种情况下,请求获得服务不可用信息,返回503状态码。

2、相关结构体

ngx_http_limit_req_conf_t

typedef struct {

ngx_shm_zone_t              *shm_zone;

ngx_uint_t                   burst;           //1等价于0.001r/s

ngx_uint_t                   limit_log_level;

ngx_uint_t                   delay_log_level;

ngx_uint_t                   nodelay;

} ngx_http_limit_req_conf_t;

备注:该结构用于存放limit_req指令的相关信息。

ngx_http_limit_req_node_t

typedef struct {

u_char                       color;

u_char                       dummy;

u_short                      len;

ngx_queue_t                  queue;

ngx_msec_t                   last;

ngx_uint_t                    excess;          //1等价于0.001 r/s

u_char                       data[1];

} ngx_http_limit_req_node_t;

备注:该结构用于存放每个客户端节点的相关信息。

ngx_http_limit_req_shctx_t

typedef struct {

ngx_rbtree_t                  rbtree;

ngx_rbtree_node_t             sentinel;

ngx_queue_t                  queue;

} ngx_http_limit_req_shctx_t;

备注:该结构体用于管理客户端节点信息,方式主要有队列和红黑树。

ngx_http_limit_req_ctx_t

typedef struct {

ngx_http_limit_req_shctx_t    *sh;

ngx_slab_pool_t             *shpool;

ngx_uint_t                   rate;             //1等价于0.001 r/s

ngx_int_t                    index;

ngx_str_t                    var;

} ngx_http_limit_req_ctx_t;

备注:该结构用于存放limit_req_zone指令的相关信息。

结构体关系

3、功能函数

3.1 初始化ctx

ngx_http_limit_req_create_conf(ngx_conf_t *cf);

函数功能:创建limit_req模块使用的结构体ngx_http_limit_req_conf_t,并初始化。

ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,

void *child);

函数功能:在location级别合并上级的配置,即server级别配置的limit_req在location级别也是有效的。

ngx_http_limit_req_init(ngx_conf_t *cf)

函数功能:将ngx_http_limit_req_handler添加到&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers的处理数组中,即在nginx处理用户请求前调用ngx_http_limit_req_handler函数。

3.2 初始化commands

ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

typedef struct {

ngx_http_limit_req_shctx_t    *sh;

ngx_slab_pool_t             *shpool;

ngx_uint_t                   rate;       //rate*1000/scale

ngx_int_t                    index;      //存放$binary_remote_addr的index

ngx_str_t                    var;        //存放具体的$binary_remote_addr

} ngx_http_limit_req_ctx_t;

shm_zone->init = ngx_http_limit_req_init_zone;

shm_zone->data = ctx;

函数功能:申请共享内存,并将limit_req_zone的配置参数放入到ngx_http_limit_req_ctx_t结构中,并使用ngx_http_limit_req_init_zone函数初始化sh和shpool。

ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)

函数功能:初始化共享内存,nginx使用共享内存的主要目的是进程间通信,并且可以在用户使用kill –HUP的时候,数据不被清零,即起到了数据累积的作用;

ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

typedef struct {

ngx_shm_zone_t              *shm_zone;

ngx_uint_t                   burst;

ngx_uint_t                   limit_log_level;

ngx_uint_t                   delay_log_level;

ngx_uint_t                   nodelay; /* unsigned  nodelay:1 */

} ngx_http_limit_req_conf_t;

函数功能:对配置文件的limit_req指令的参数进行解析,并将配置参数加入到结构体ngx_http_limit_req_conf_t中。

3.2 数据handle

ngx_http_limit_req_handler(ngx_http_request_t *r)

函数功能:请求的处理函数。主要步骤如下所示:

(1)lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module),读取位置部分的配置到lrcf中;

(2)vv = ngx_http_get_indexed_variable(r, ctx->index),根据索引得到变量值如$binary_remote_addr;

(3)ngx_http_limit_req_expire(ctx, 1),删除too old的节点;

(4)rc=ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess),查找客户端节点信息,并得到相应的状态信息如NGX_BUSY、NGX_AGAIN、NGX_OK、NGX_ DECLINED;

(5)根据rc的返回值,进行相应的处理;

ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)

函数功能:删除too old的节点。

ngx_http_limit_req_delay(ngx_http_request_t *r);

函数功能:延迟处理用户请求。

ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf…)

函数功能:通过红黑树查找用户节点,并对节点的两次访问间隔频率进行计算,返回NGX_BUSY、NGX_AGAIN、NGX_OK、NGX_ DECLINED共4种状态。

(1)NGX_ DECLINED:节点不存在;

(2)NGX_OK:该客户端访问频率未超过设定值;

(3)NGX_AGAIN:该客户端访问频率超过了设定值,但是并未超过阈值(与burst有关);

(4)NGX_BUSY:该客户端访问频率超过了阈值;

备注:该函数是整个模块的核心,算法思想是令牌桶算法。令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据数目,并允许突发数据的发送。

令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。令牌桶算法的基本过程如下:

  (1)假如用户配置的平均发送速率为10r/s,则每隔0.1秒一个令牌被加入到桶中;

  (2)假设桶最多可以存发b个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;

  (3)当一个n个字节的数据包到达时,就从令牌桶中删除n个令牌,并且数据包被发送到网络;

  (4)如果令牌桶中少于n个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外;

  (5)算法允许最长b个字节的突发,但从长期运行结果看,数据包的速率被限制成常量r。对于在流量限制外的数据包可以以不同的方式处理:

它们可以被丢弃;

它们可以排放在队列中以便当令牌桶中累积了足够多的令牌时再传输;

它们可以继续发送,但需要做特殊标记,网络过载的时候将这些特殊标记的包丢弃。

注意:令牌桶算法不能与另外一种常见算法“漏桶算法(Leaky Bucket)”相混淆。这两种算法的主要区别在于“漏桶算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输数据外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。

tp = ngx_timeofday();

now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);

ms = (ngx_msec_int_t) (now - lr->last);

excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;

//令牌桶算法:每来一个请求分配一个令牌1000

//rate*ms = 1s内该请求所花的时间< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

//excess = 1s的余量

if (excess < 0) {                                                      //频率很低

excess = 0;

}

*ep = excess;

if ((ngx_uint_t) excess > lrcf->burst) {              // 1s可以并发burst个请求

return NGX_BUSY;

}

lr->excess = excess;

lr->last = now;

if (excess) {

return NGX_AGAIN;

}

return NGX_OK;

ngx_http_limit_req_rbtree_insert_value (ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)

函数功能:通过红黑树结构插入节点。

5、流程图

模块入口(ngx_module_t)

ngx_module_t  ngx_http_limit_req_module 是整个模块的入口,它定义了它支持的指令入口和模块配置文件初始化的入口。

模块上下文(ngx_http_module_t)

这个结构体的主要功能是用来创建三个部分( main 、 server 、 location )的配置和合并配置。主要包括以下几个函数:

(1)读入配置文件前调用;

(2)读入配置文件后调用;

(3)创建全局部分配置时调用;

(4)初始化全局部分配置时调用;

(5)创建主机部分配置时调用;

(6)与全局部分配置合并时调用;

(7)创建位置部分配置时调用;

(8)与主机部分配置合并时调用;

而在limit_req模块我们关注的是(2)、(7)和(8)。模块的处理顺序是(7)->(8)->(2),create函数用来为特定的位置部分的配置结构体分配内存,merge函数用来设定默认值和与继承过来的配置合并,这个合并函数还要负责检验读入的数值是否有效,postconfig函数用来初始化处理函数。

在本模块中,create、merge函数的主要功能是:对模块的日志级别进行设置。

模块指令(ngx_command_t)

ngx_http_limit_req_zone的主要功能:

(1)解析配置文件的命令参数:name、size(K/M)、scale(r/s、r/m)、rate;

(2)申请配置文件空间ngx_http_limit_req_ctx_t,填充参数;

(3)申请共享内存,并初始化ngx_http_limit_req_init_zone;

shm_zone->init = ngx_http_limit_req_init_zone;

shm_zone->data = ctx;

转载于:https://my.oschina.net/kone/blog/88713

Nginx模块开发(10)—limit_req模块分析相关推荐

  1. php magento 开发,magento 2模块开发实例helloworld模块 hello world 程序 c语言hello world代码 c语言hello worl...

    data-id="1190000005008433" data-license="cc"> 1.在app/etc/config.php中添加自定义的模块( ...

  2. 解决 Gradle 进行多模块开发时,模块相互依赖的问题

    问题背景 在使用多模块开发时,通常一个模块(A)可能会需要其它模块(B)中的类或方法,这时就产生了依赖关系,也就是 A 依赖 B. 要解决上述依赖,有两种方案 1.将B发布到 repo 仓库(可以为本 ...

  3. 搭建基于ASP.NET 2.0的DNN 4.X模块开发环境及模块实例(2)

    群里一直有朋友在问如何构建基于ASP.NET 2.0的DNN 4.X模块开发环境,受原来ASP.NET1.1多工程机制的思维影响,大家一直在等待VS2005支持多工程,经过一段时间的学习和摸索,发现其 ...

  4. 【Linux网络编程】Nginx -- 模块开发(upstream / subrequest)

    [Linux网络编程]Nginx -- 模块开发(upstream / subrequest) [1]upstream VS subrequest 简介 upstream 为访问上游服务器,它把Ngi ...

  5. 全志Tina Linux Camera 摄像头模块开发指南 全网最详细版本支持百问网T113-Pro DongshanPI-NezhaD1-H DongshanPI-D1s V853-Pro等开发板

    1 概述 编写目的:介绍camera 模块在sunxi 平台上的开发流程. 适用范围:本文档目前适用于tina3.0 以上具备camera 的硬件平台. 2 模块介绍 2.1 模块功能介绍 用于接收并 ...

  6. springboot的多模块开发

    文章目录 springboot的多模块开发 1.创建项目springboot-high 2.在项目中添加模块 1)springboot-common模块 2)springboot-domain模块 3 ...

  7. laravel5.2基础多模块开发(pingpong/modules)

    2019独角兽企业重金招聘Python工程师标准>>> 1.下载laravel5.2 http://laravelacademy.org/resources-download 2.解 ...

  8. Android开发之ApiCloud模块开发步骤

    看图操作,简单明了: 好了apicloud模块开发完成,你可以打包arr文件压缩zip后上传到自定义模块然后别人用js就可以引用你开发的这个模块里面的内容了 打包arr文件压缩zip步骤如下图: 上传 ...

  9. OpenCart 官方开发指南翻译一 —— 模块开发

    模块开发   编写 OpenCart 模块可以很好地了解 OpenCart 如何运作的基本原理.就像 OpenCart 的其余部分一样,模块遵循 MVCL 设计模式.本文档指南将介绍如何使用 MVC- ...

  10. 微信小程序之网易云音乐(四)- 排行、歌手及歌手详情页模块开发

    微信小程序之网易云音乐(四)- 排行.歌手及歌手详情页模块开发 一. 排行模块开发 二. 歌手模块开发 三. 歌手详情页开发 微信小程序之网易云音乐导航 一. 排行模块开发 rank.vue文件: & ...

最新文章

  1. C++ queue 详细介绍
  2. SSL证书安装指南 - Winodws 2003 Server IIS 6.0
  3. 回文数python_回文数 python
  4. MySQL—隔离级别
  5. PHP 常用数据库操作
  6. matlab绘制8条曲线,科学网—【Matlab】如何用plotyy对应坐标绘制多条曲线 - 叶瑞杰的博文...
  7. C# 获得两日期之间所有月份(包括跨年)
  8. 老程序员也搞不定的 4 个巨坑!
  9. python基础教程百度云-python从入门到精通视频教程百度云资源
  10. 关于html中利用jQuery选择子节点方法总结——待续
  11. 20佳非常有创意的About页面设计
  12. LINUX下载编译python
  13. PSPNet编译心得
  14. 数据不平衡问题——SMOTE算法赏析
  15. 《系统集成项目管理工程师》必背知识点
  16. win10远程桌面连接凭据怎么设置_如何解决Win10远程桌面提示你的凭证不工作?...
  17. 你的APK安全吗?来WeTest免费测!
  18. 【多源融合】自适应卡尔曼滤波的多种形式:遗忘卡尔曼滤波、渐消记忆卡尔曼滤波和自适应卡尔曼滤波
  19. linux后加网卡,Linux添加网卡教程
  20. 快速学习Ant Design-入门

热门文章

  1. mysql 最小值对应的其他属性_查询最小值对应的非group by字段
  2. linux 下的带宽、延时、吞吐率、PPS
  3. CentOS 6系统FreeSwitch和RTMP服务 安装及演示(二)
  4. android Studio Error: 前言中不允许有内容
  5. 使用扩展欧几里得算法对逆元求解
  6. 判断没登录就跳转php,PHP实例:PHP判断用户是否已经登录(跳转到不同页面或者执行不同动作)...
  7. 全国各省市县统计年鉴/中国环境统计年鉴/中国工业企业数据库/中国专利数据库/污染排放数据库
  8. 比较x^y和y^x的大小
  9. Java 中的枚举 (enum)
  10. 云计算 码率适配限速_5G 成熟后,带宽足够且云计算力够大,会不会对 PC 的升级需求放缓?...