nginx-1.22.1 limit_req功能在C底层实现

##nginx.conf配置文件limit_req配置

##nginx限制访问频率,限流

http {

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

        server {
                listen       8103;
                server_name  localhost;

                location ~ ^/yym/ {
                    root   /home/yym/nginx_web/yym-vue3/;
                    index  index.html index.htm;
                    try_files $uri $uri/ /index.html;
                    limit_req zone=one burst=1 nodelay;
                    #limit_conn addr 1;
                    #limit_conn_status 503;
                    #limit_rate_after 10240K;
                    #limit_rate 50k;
                }

        }

}

##ngx_http_limit_req_init方法

#0  ngx_http_limit_req_init (cf=0x7fffffffdc80) at src/http/modules/ngx_http_limit_req_module.c:1092
#1  0x00005555555b8a89 in ngx_http_block (cf=0x7fffffffdc80, cmd=0x5555556640a0 <ngx_http_commands>, conf=0x555555696988) at src/http/ngx_http.c:310
#2  0x0000555555594031 in ngx_conf_handler (cf=0x7fffffffdc80, last=1) at src/core/ngx_conf_file.c:463
#3  0x0000555555593b34 in ngx_conf_parse (cf=0x7fffffffdc80, filename=0x5555556958e8) at src/core/ngx_conf_file.c:319
#4  0x000055555558f2fb in ngx_init_cycle (old_cycle=0x7fffffffde50) at src/core/ngx_cycle.c:284
#5  0x000055555556e66b in main (argc=3, argv=0x7fffffffe1f8) at src/core/nginx.c:292

##ngx_http_limit_req_handler函数指针初始化到cmcf结构体

 ngx_http_core_main_conf_t  *cmcf;

*h = ngx_http_limit_req_handler;

指针函数赋予cmcf结构体handlers

##ngx_http_limit_req_handler方法

#0  ngx_http_limit_req_handler (r=0x5555556c6fd0) at src/http/modules/ngx_http_limit_req_module.c:196
#1  0x00005555555bcd66 in ngx_http_core_generic_phase (r=0x5555556c6fd0, ph=0x5555556c92c0) at src/http/ngx_http_core_module.c:897
#2  0x00005555555bcd00 in ngx_http_core_run_phases (r=0x5555556c6fd0) at src/http/ngx_http_core_module.c:875
#3  0x00005555555bcc69 in ngx_http_handler (r=0x5555556c6fd0) at src/http/ngx_http_core_module.c:858
#4  0x00005555555cb829 in ngx_http_process_request (r=0x5555556c6fd0) at src/http/ngx_http_request.c:2120
#5  0x00005555555ca302 in ngx_http_process_request_headers (rev=0x5555556cd5b0) at src/http/ngx_http_request.c:1498
#6  0x00005555555c981e in ngx_http_process_request_line (rev=0x5555556cd5b0) at src/http/ngx_http_request.c:1165
#7  0x00005555555c8f10 in ngx_http_wait_request_handler (rev=0x5555556cd5b0) at src/http/ngx_http_request.c:503
#8  0x00005555555b6e69 in ngx_epoll_process_events (cycle=0x5555556956d0, timer=60000, flags=1) at src/event/modules/ngx_epoll_module.c:901
#9  0x00005555555a63ca in ngx_process_events_and_timers (cycle=0x5555556956d0) at src/event/ngx_event.c:248
#10 0x00005555555b4701 in ngx_worker_process_cycle (cycle=0x5555556956d0, data=0x0) at src/os/unix/ngx_process_cycle.c:721
#11 0x00005555555b1309 in ngx_spawn_process (cycle=0x5555556956d0, proc=0x5555555b4645 <ngx_worker_process_cycle>, data=0x0, name=0x555555646757 "worker process", respawn=-3)
    at src/os/unix/ngx_process.c:199
#12 0x00005555555b3898 in ngx_start_worker_processes (cycle=0x5555556956d0, n=1, type=-3) at src/os/unix/ngx_process_cycle.c:344
#13 0x00005555555b3069 in ngx_master_process_cycle (cycle=0x5555556956d0) at src/os/unix/ngx_process_cycle.c:130
#14 0x000055555556ea45 in main (argc=3, argv=0x7fffffffe1f8) at src/core/nginx.c:383

##ngx_http_complex_value方法 if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {

key 使用请求来源ip

1、计算key:通过ngx_http_complex_value函数,基于请求和配置中的key指令计算出实际的key值
2、检查key值:计算出的key值会被检查是否为空或过长

ngx_int_t
ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
    ngx_str_t *value)
{
    size_t                        len;
    ngx_http_script_code_pt       code;
    ngx_http_script_len_code_pt   lcode;
    ngx_http_script_engine_t      e;

    if (val->lengths == NULL) {
        *value = val->value;
        return NGX_OK;
    }

    ngx_http_script_flush_complex_value(r, val);

    ngx_memzero(&e, sizeof(ngx_http_script_engine_t));

    e.ip = val->lengths;
    e.request = r;
    e.flushed = 1;

    len = 0;

    while (*(uintptr_t *) e.ip) {
        lcode = *(ngx_http_script_len_code_pt *) e.ip;
        len += lcode(&e);
    }

    value->len = len;
    value->data = ngx_pnalloc(r->pool, len);
    if (value->data == NULL) {
        return NGX_ERROR;
    }

    e.ip = val->values;
    e.pos = value->data;
    e.buf = *value;

    while (*(uintptr_t *) e.ip) {
        code = *(ngx_http_script_code_pt *) e.ip;
        code((ngx_http_script_engine_t *) &e);
    }

    *value = e.buf;

    return NGX_OK;
}

##ngx_http_limit_req_lookup 函数中,处理未找到匹配键并准备在红黑树中插入新节点的部分

static ngx_int_t
ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
    ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account)
{
    size_t                      size;
    ngx_int_t                   rc, excess;
    ngx_msec_t                  now;
    ngx_msec_int_t              ms;
    ngx_rbtree_node_t          *node, *sentinel;
    ngx_http_limit_req_ctx_t   *ctx;
    ngx_http_limit_req_node_t  *lr;

    now = ngx_current_msec;

    ctx = limit->shm_zone->data;

    node = ctx->sh->rbtree.root;
    sentinel = ctx->sh->rbtree.sentinel;

    while (node != sentinel) {

        if (hash < node->key) {
            node = node->left;
            continue;
        }

        if (hash > node->key) {
            node = node->right;
            continue;
        }

        /* hash == node->key */

        lr = (ngx_http_limit_req_node_t *) &node->color;

        rc = ngx_memn2cmp(key->data, lr->data, key->len, (size_t) lr->len);

        if (rc == 0) {
            ngx_queue_remove(&lr->queue);
            ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);

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

            if (ms < -60000) {
                ms = 1;

            } else if (ms < 0) {
                ms = 0;
            }

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

            if (excess < 0) {
                excess = 0;
            }

            *ep = excess;

            if ((ngx_uint_t) excess > limit->burst) {
                return NGX_BUSY;
            }

            if (account) {
                lr->excess = excess;

                if (ms) {
                    lr->last = now;
                }

                return NGX_OK;
            }

            lr->count++;

            ctx->node = lr;

            return NGX_AGAIN;
        }

        node = (rc < 0) ? node->left : node->right;
    }

    *ep = 0;

    size = offsetof(ngx_rbtree_node_t, color)
           + offsetof(ngx_http_limit_req_node_t, data)
           + key->len;

    ngx_http_limit_req_expire(ctx, 1);

    node = ngx_slab_alloc_locked(ctx->shpool, size);

    if (node == NULL) {
        ngx_http_limit_req_expire(ctx, 0);

        node = ngx_slab_alloc_locked(ctx->shpool, size);
        if (node == NULL) {
            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                          "could not allocate node%s", ctx->shpool->log_ctx);
            return NGX_ERROR;
        }
    }

    node->key = hash;

    lr = (ngx_http_limit_req_node_t *) &node->color;

    lr->len = (u_short) key->len;
    lr->excess = 0;

    ngx_memcpy(lr->data, key->data, key->len);

    ngx_rbtree_insert(&ctx->sh->rbtree, node);

    ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);

    if (account) {
        lr->last = now;
        lr->count = 0;
        return NGX_OK;
    }

    lr->last = 0;
    lr->count = 1;

    ctx->node = lr;

    return NGX_AGAIN;
}

##ngx_http_limit_req_expire尝试清理过期节点,ngx_slab_alloc_locked分配node空间

 ngx_http_limit_req_expire(ctx, 1);

 node = ngx_slab_alloc_locked(ctx->shpool, size);

##共享内存初始化,分配内存

if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {

            goto failed;

 }

ngx_int_t
ngx_shm_alloc(ngx_shm_t *shm)
{
    shm->addr = (u_char *) mmap(NULL, shm->size,
                                PROT_READ|PROT_WRITE,
                                MAP_ANON|MAP_SHARED, -1, 0);

    if (shm->addr == MAP_FAILED) {
        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
                      "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);
        return NGX_ERROR;
    }

    return NGX_OK;
}
#0  ngx_shm_alloc (shm=0x555555695d70) at src/os/unix/ngx_shmem.c:17
#1  0x000055555558fdbb in ngx_init_cycle (old_cycle=0x7fffffffde60) at src/core/ngx_cycle.c:485
#2  0x000055555556e66b in main (argc=3, argv=0x7fffffffe208) at src/core/nginx.c:292


(gdb) p *shm
$1 = {addr = 0x0, size = 31457280, name = {len = 3, data = 0x5555556aa179 "one:30m"}, log = 0x5555556956e8, exists = 0}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/925613.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 和 Pyecharts 对Taptap相关数据可视化分析

结果展示&#xff1a; 数据来源&#xff1a; Python爬取TapTap 热门游戏信息并存储到数据库&#xff08;详细版&#xff09; 目录 结果展示&#xff1a; 数据来源&#xff1a; Python爬取TapTap 热门游戏信息并存储到数据库&#xff08;详细版 一、引言 二、准备工作 三、…

Atiyah交换代数经典入门教材:Introduction to Commutative Algebra

在上帖中&#xff0c;我分享了Zariski的交换代数教材&#xff1a;Zariski交换代数经典教材Commutative Algebra系列&#xff08;pdf可复制版&#xff09;。其实交换代数方面&#xff0c;除了Zariski的教材&#xff0c;还有Atiyah的Introduction to Commutative Algebra&#xf…

ADAM优化算法与学习率调度器:深度学习中的关键工具

深度学习模型的训练效果离不开优化算法和学习率的选择。ADAM&#xff08;Adaptive Moment Estimation&#xff09;作为深度学习领域中广泛应用的优化算法之一&#xff0c;以其高效性和鲁棒性成为许多任务的默认选择。而学习率调度器则是优化算法的“助推器”&#xff0c;帮助训…

SuperMap Objects组件式GIS开发技术浅析

引言 随着GIS应用领域的扩展&#xff0c;GIS开发工作日显重要。一般地&#xff0c;从平台和模式上划分&#xff0c;GIS二次开发主要有三种实现方式&#xff1a;独立开发、单纯二次开发和集成二次开发。上述的GIS应用开发方式各有利弊&#xff0c;其中集成二次开发既可以充分利…

DM达梦管理工具拖出空白区块,无法关闭

1. 出现问题&#xff1a;DM达梦管理工具拖出空白区块&#xff0c;无法关闭。 2. 解决方法 新建查询页&#xff0c;把查询页拖到空白区块里&#xff0c;完全覆盖空白区块。之后空白区块会变成查询页&#xff0c;右上角会出现叉号&#xff0c;点击叉号关闭就行。 3. 后记 达梦…

idea_卸载与安装

卸载与安装 卸载1、设置 -> 应用2、查找到应用&#xff0c;点击卸载3、把删除记录和设置都勾选上4、删除其它几个位置的残留 安装1、下载安装包2、欢迎安装 -> Next3、选择安装目录 -> Next4、创建快捷图标和添加到环境变量5、确认文件夹的名称 -> Install6、完成安…

学习threejs,使用specularMap设置高光贴图

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshPhongMaterial高…

UR开始打中国牌,重磅发布国产化协作机器人UR7e 和 UR12e

近日&#xff0c;优傲&#xff08;UR&#xff09;机器人公司立足中国市场需求&#xff0c;重磅推出UR7e和UR12e 两款本地化协作机器人。它们延续优傲&#xff08;UR&#xff09;一以贯之的高品质与性能特质&#xff0c;着重优化负载自重比&#xff0c;且在价格层面具竞争力&…

2024年陕西科技大学数据结构程序填空题+预测

递归实现插入排序 #include <stdio.h>void insertion_sort(int arr[], int n) {if (n > 1){insertion_sort(arr, n - 1);arr[0] arr[n];int i;for (i n - 1; i > 0; i--){if (arr[i] > arr[0]){arr[i 1] arr[i];}else{break;}}arr[i 1] arr[0];} }int m…

OGRE 3D----3. OGRE绘制自定义模型

在使用OGRE进行开发时,绘制自定义模型是一个常见的需求。本文将介绍如何使用OGRE的ManualObject类来创建和绘制自定义模型。通过ManualObject,开发者可以直接定义顶点、法线、纹理坐标等,从而灵活地构建各种复杂的几何体。 Ogre::ManualObject 是 Ogre3D 引擎中的一个类,用…

基于PoE交换机的智慧停车场监控组网应用

伴随城市发展快速&#xff0c;汽车保有量也不断增长&#xff0c;导致停车管理问题也愈发凸显。针对包括路侧停车位、地面停车场、地下停车场等场景的停车管理需求&#xff0c;通常会部署监控设备进行车位监测、现场安全监测等&#xff0c;助力构建智能化停车管理。因此如何为分…

直接抄作业!Air780E模组LuatOS开发:位运算(bit)示例

在嵌入式开发中&#xff0c;位运算是一种高效且常用的操作技巧。本文将介绍如何使用Air780E模组和LuatOS进行位运算&#xff0c;并通过示例代码帮助读者快速上手。 一、位运算概述 位运算是一种在计算机系统中对二进制数位进行操作的运算。由于计算机内部数据的存储和处理都是…

多点DMALL启动招股:将在港交所上市,聚焦数字零售服务

近日&#xff0c;多点数智有限公司&#xff08;Dmall Inc.&#xff0c;下称“多点”或“多点DMALL”&#xff09;发布全球发售文件&#xff0c;于11月28日至12月3日招股&#xff0c;预计将于2024年12月6日在港交所主板挂牌上市。 招股书显示&#xff0c;多点DMALL本次全球发售的…

WRF-Chem模式安装、环境配置、原理、调试、运行方法;数据准备及相关参数设置方法

大气污染是工农业生产、生活、交通、城市化等方面人为活动的综合结果&#xff0c;同时气象因素是控制大气污染的关键自然因素。大气污染问题既是局部、当地的&#xff0c;也是区域的&#xff0c;甚至是全球的。本地的污染物排放除了对当地造成严重影响外&#xff0c;同时还会在…

离线安装 Docker-IO:详细步骤指南

离线安装 Docker-IO:详细步骤指南 一、准备工作1.1 下载 Docker 离线安装包1.2 准备安装环境1.3 配置防火墙和 SELinux(可选)二、上传和解压离线安装包2.1 上传安装包2.2 解压安装包三、安装 Docker-IO3.1 移动 Docker 文件到系统目录3.2 配置 Docker 服务3.3 赋予服务文件执…

拥抱 OpenTelemetry:阿里云 Java Agent 演进实践

作者&#xff1a;陈承 背景 在 2018 年的 2 月&#xff0c;ARMS Java Agent 的第一个版本正式发布&#xff0c;为用户提供无侵入的的可观测数据采集服务。6 年后的今天&#xff0c;随着软件技术的迅猛发展、业务场景的逐渐丰富、用户规模的快速增长&#xff0c;我们逐渐发现过…

【信息系统项目管理师】第3章:信息系统治理 考点梳理

文章目录 3.1 IT 治理3.1.1 IT治理基础3.1.2 IT治理体系3.1.3 IT治理任务3.1.4 IT治理方法与标准 3.2 IT 审计3.2.1 IT审计基础3.2.2 审计方法与技术3.2.3 审计流程3.2.4 审计内容 3.1 IT 治理 IT治理起到重要的统筹、评估、指导和监督作用。 信息技术审计(IT审计)作为与IT治…

DRM(数字权限管理技术)防截屏录屏----ffmpeg安装

提示&#xff1a;ffmpeg安装 文章目录 [TOC](文章目录) 前言一、下载二、配置环境变量三、运行ffmpeg四、文档总结 前言 FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的…

github webhooks 实现网站自动更新

本文目录 Github Webhooks 介绍Webhooks 工作原理配置与验证应用云服务器通过 Webhook 自动部署网站实现复制私钥编写 webhook 接口Github 仓库配置 webhook以服务的形式运行 app.py Github Webhooks 介绍 Webhooks是GitHub提供的一种通知方式&#xff0c;当GitHub上发生特定事…

全桥LLC变换器原理及MATLAB仿真模型

“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主电路拓扑 全桥LLC 谐振变换器主电路拓扑结构图。图中S1 &#xff5e; S4为功率开关管&#xff0c; D1 &#xff5e; D4为功率开关管的体二极管&#xff0c; C1 &#xff5e; C4 为功率开关管的寄生电容。谐振电感r…