远程协助
当前位置:重庆拓磊计算机运营维护中心 > 文档中心 > 服务器 >
标题:Nginx源码研究之nginx限流模块详解    日期:2018-10-06

高并发系统有三把利器:缓存、降级和限流;

限流的目的是通过对并发访问/请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页)、排队等待(秒杀)、降级(返回兜底数据或默认数据);

高并发系统常见的限流有:限制总并发数(数据库连接池)、限制瞬时并发数(如nginx的limit_conn模块,用来限制瞬时并发连接数)、限制时间窗口内的平均速率(nginx的limit_req模块,用来限制每秒的平均速率);

另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。

1.限流算法

最简单粗暴的限流算法就是计数器法了,而比较常用的有漏桶算法和令牌桶算法;

1.1计数器

计数器法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。

那么我们我们可以设置一个计数器counter,其有效时间为1分钟(即每分钟计数器会被重置为0),每当一个请求过来的时候,counter就加1,如果counter的值大于100,就说明请求数过多;

这个算法虽然简单,但是有一个十分致命的问题,那就是临界问题。

如下图所示,在1:00前一刻到达100个请求,1:00计数器被重置,1:00后一刻又到达100个请求,显然计数器不会超过100,所有请求都不会被拦截;

然而这一时间段内请求数已经达到200,远超100。

Nginx源码研究之nginx限流模块详解

1.2 漏桶算法

如下图所示,有一个固定容量的漏桶,按照常量固定速率流出水滴;如果桶是空的,则不会流出水滴;流入到漏桶的水流速度是随意的;如果流入的水超出了桶的容量,则流入的水会溢出(被丢弃);

可以看到漏桶算法天生就限制了请求的速度,可以用于流量整形和限流控制;

Nginx源码研究之nginx限流模块详解

1.3 令牌桶算法

令牌桶是一个存放固定容量令牌的桶,按照固定速率r往桶里添加令牌;桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃;

当一个请求达到时,会尝试从桶中获取令牌;如果有,则继续处理请求;如果没有则排队等待或者直接丢弃;

可以发现,漏桶算法的流出速率恒定或者为0,而令牌桶算法的流出速率却有可能大于r;

Nginx源码研究之nginx限流模块详解

2.nginx基础知识

Nginx主要有两种限流方式:按连接数限流(ngx_http_limit_conn_module)、按请求速率限流(ngx_http_limit_req_module);

学习限流模块之前还需要了解nginx对HTTP请求的处理过程,nginx事件处理流程等;

2.1HTTP请求处理过程

nginx将HTTP请求处理流程分为11个阶段,绝大多数HTTP模块都会将自己的handler添加到某个阶段(其中有4个阶段不能添加自定义handler),nginx处理HTTP请求时会挨个调用所有的handler;

typedef enum {
 NGX_HTTP_POST_READ_PHASE = 0, //目前只有realip模块会注册handler(nginx作为代理服务器时有用,后端以此获取客户端原始ip)
 
 NGX_HTTP_SERVER_REWRITE_PHASE, //server块中配置了rewrite指令,重写url
 
 NGX_HTTP_FIND_CONFIG_PHASE, //查找匹配location;不能自定义handler;
 NGX_HTTP_REWRITE_PHASE,  //location块中配置了rewrite指令,重写url
 NGX_HTTP_POST_REWRITE_PHASE, //检查是否发生了url重写,如果有,重新回到FIND_CONFIG阶段;不能自定义handler;
 
 NGX_HTTP_PREACCESS_PHASE,  //访问控制,限流模块会注册handler到此阶段
 
 NGX_HTTP_ACCESS_PHASE,  //访问权限控制
 NGX_HTTP_POST_ACCESS_PHASE, //根据访问权限控制阶段做相应处理;不能自定义handler;
 
 NGX_HTTP_TRY_FILES_PHASE,  //只有配置了try_files指令,才会有此阶段;不能自定义handler;
 NGX_HTTP_CONTENT_PHASE,  //内容产生阶段,返回响应给客户端
 
 NGX_HTTP_LOG_PHASE   //日志记录
} ngx_http_phases;

nginx使用结构体ngx_module_s表示一个模块,其中字段ctx,是一个指向模块上下文结构体的指针;nginx的HTTP模块上下文结构体如下所示(上下文结构体的字段都是一些函数指针):

typedef struct {
 ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
 ngx_int_t (*postconfiguration)(ngx_conf_t *cf); //此方法注册handler到相应阶段
 
 void  *(*create_main_conf)(ngx_conf_t *cf); //http块中的主配置
 char  *(*init_main_conf)(ngx_conf_t *cf, void *conf);
 
 void  *(*create_srv_conf)(ngx_conf_t *cf); //server配置
 char  *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
 
 void  *(*create_loc_conf)(ngx_conf_t *cf); //location配置
 char  *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
下一篇:IIS 7.5 使用URL Rewrite模块的简单设置实现网页跳转

联系我们
  • 客服热线:023-63522929(7 x 24h)
  • 在线客服:
  • 微信公众号 官方微博