当前位置: 首页 > article >正文

深入理解nginx的请求限速模块[下]

目录

  • 3. 源码分析
  • 3.1 配置指令
    • 3.1.1 limit_req_zone指令
      • 3.1.2 limit_req指令
      • 3.1.3 limit_req_dry_run指令
      • 3.1.4 limit_req_log_level指令
      • 3.1.5 limit_req_status指令
    • 3.2 模块初始化
    • 3.3 请求处理
      • 3.3.1 ngx_http_limit_req_handler
      • 3.3.1 ngx_http_limit_req_lookup
      • 3.3.2 ngx_http_limit_req_account

上接 深入理解nginx的请求限速模块[上]](https://blog.csdn.net/bluestn/article/details/136710631)

3. 源码分析

3.1 配置指令

3.1.1 limit_req_zone指令

  limit_req_zone指令的作用是定义一个共享内存区,用于在worker进程间共享限速的状态信息,因此请求限速模块的限速功能是服务器级别的,而不是单个worker进程级别的。其配置指令定义如下:

    {
    ngx_string("limit_req_zone"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3,
      ngx_http_limit_req_zone,
      0,
      0,
      NULL 
    },

   ngx_http_limit_req_zone函数的重要逻辑就是解析相应的参数,然后创建共享内存区:

static char *
ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
   
......
	ngx_http_limit_req_ctx_t *ctx;
......  

	ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t));

	解析配置指令
......

    ctx->rate = rate * 1000 / scale;

	/* 创建共享内存区 */
    shm_zone = ngx_shared_memory_add(cf, &name, size,
                                     &ngx_http_limit_req_module);
    if (shm_zone == NULL) {
   
        return NGX_CONF_ERROR;
    }

    if (shm_zone->data) {
   
        ctx = shm_zone->data;

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "%V \"%V\" is already bound to key \"%V\"",
                           &cmd->name, &name, &ctx->key.value);
        return NGX_CONF_ERROR;
    }

    shm_zone->init = ngx_http_limit_req_init_zone;
    shm_zone->data = ctx;     /* 设置共享内存区的上下文信息 */
}

3.1.2 limit_req指令

  limit_req指令则是开启请求限速功能,它需要引用前面limit_req_zone指令定义的共享内存区,并且指定允许的busrt突发值和delay值。其配置指令定义如下:

    {
    ngx_string("limit_req"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
      ngx_http_limit_req,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },
static char *
ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
   
	ngx_http_limit_req_conf_t *lrcf = conf;
	ngx_http_limit_req_limit_t *limit, *limits;

	......
	解析配置指令


	/* 如果还没有创建限速规则数组,则创建一个 */	
    limits = lrcf->limits.elts;

    if (limits == NULL) {
   
        if (ngx_array_init(&lrcf->limits, cf->pool, 1,
                           sizeof(ngx_http_limit_req_limit_t))
            != NGX_OK)
        {
   
            return NGX_CONF_ERROR;
        }
    }

    for (i = 0; i < lrcf->limits.nelts; i++) {
   
        if (shm_zone == limits[i].shm_zone) {
   
            return "is duplicate";
        }
    }

	/* 将当前limit_req指令添加到lrcf->limits数组中 */
    limit = ngx_array_push(&lrcf->limits);
    if (limit == NULL) {
   
        return NGX_CONF_ERROR;
    }

    limit->shm_zone = shm_zone;
    limit->burst = burst * 1000;    /* busrt的单位是r/ms,所以乘以1000 */
    limit->delay = delay * 1000;    /* delay的单位是r/ms,所以乘以1000 */

    return NGX_CONF_OK;
}

3.1.3 limit_req_dry_run指令

   该指令设置了一个开关,如果是on的话,如果发生了限流事件,只是在error日志中打印日志,而不是实际执行限流动作。这个指令主要用于开启限流操作前进行测试验证工作。配置指令定义如下:

    {
    ngx_string("limit_req_dry_run"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_limit_req_conf_t, dry_run),
      NULL },

3.1.4 limit_req_log_level指令

  该指令设置了当发生限流事件的时候,在nginx的error日志中输出的日志的日志级别。配置指令定义如下:

    {
    ngx_string("limit_req_log_level"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_enum_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_limit_req_conf_t, limit_log_level),
      &ngx_http_limit_req_log_levels },

3.1.5 limit_req_status指令

  该指令设置了当发生限流事件的时候,nginx返回给客户端的响应码。


    {
    ngx_string("limit_req_status"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,</

http://www.kler.cn/news/274183.html

相关文章:

  • 代码随想录算法训练营 DAY 14 | 二叉树的递归遍历和迭代遍历
  • 中间件-消息队列
  • git的起源
  • JavaScript中new操作符具体干了什么
  • 【LIMS】微服务
  • 前端项目,个人笔记(三)【Vue-cli - api封装-axios使用举例】
  • c++ 自己实现一个迭代器
  • golang面试题总结
  • sparksession对象简介
  • 网页的制作
  • Linux 建立链接(ln)
  • (学习日记)2024.03.16:UCOSIII第十八节:任务的删除
  • 数据结构奇妙旅程之红黑树
  • 大语言模型(LLM)Token 概念
  • SpringBoot集成Jasypt实现敏感信息加密
  • python连接mysql数据库步骤
  • nfs介绍与配置
  • 2024年企业经济管理与大数据国际会议(ICEEMBD 2024)
  • 【React 】如何提高组件的渲染效率?在React中如何避免不必要的render?
  • CTF题型 SSTI(2) Flask-SSTI典型题巩固