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}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 混淆问题

我的安卓混淆只需要在gradle里面开启就行了。 buildTypes {release {minifyEnabled trueshrinkResources truezipAlignEnabled trueproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro}} minifyEnabled true 这个就是开启方法&#xf…

XELA - uSkin 三轴触觉传感器:为机器人赋予敏锐触感

XELA Robotics 的 uSkin 触觉传感器以其创新性在机器人技术中备受关注。它凭借高密度设计和三轴力测量能力&#xff0c;大幅提升了机器人的触觉感知能力&#xff0c;这种技术不但增强了机器人的智能化和柔性&#xff0c;还为不同行业的应用创造了广泛的可能性。其中在机器人灵巧…

【前端开发】老年模式:字体大小设置

导入插件&#xff1a;npm install postcss-px-to-viewport--save-dev postcss-px-to-viewport&#xff1a;将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件 在根目录下新建文件&#xff1a;postcss.config.js const path require(“path”); module.exports …

k8s集成skywalking

如果能科学上网的话&#xff0c;安装应该不难&#xff0c;如果有问题可以给我留言 本篇文章我将给大家介绍“分布式链路追踪”的内容&#xff0c;对于目前大部分采用微服务架构的公司来说&#xff0c;分布式链路追踪都是必备的&#xff0c;无论它是传统微服务体系亦或是新一代…

Card组件的用法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了DataTable的排序功能相关的内容,本章回中将介绍Card Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的Card Widget是一种容器类组件,它可以包含其它的组件,它的大小随着被包含…

【人工智能】Python与强化学习:从零实现多臂老虎机(Multi-Armed Bandit)问题

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 强化学习是一种模仿生物行为的学习方法,在不确定环境中寻找最优策略。多臂老虎机(Multi-Armed Bandit, MAB)是强化学习的经典问题之一,模拟了在多个选择中如何平衡探索和利用,以获取最大的长期回报。…

Ubuntu WiFi检测

ubuntu检测到多个同名wifi&#xff0c;怎么鉴别假冒的wifi&#xff1f; 在Ubuntu中&#xff0c;如果检测到多个同名的Wi-Fi网络&#xff0c;可能存在假冒的Wi-Fi&#xff08;例如“蜜罐”攻击&#xff09;。以下是一些鉴别假冒Wi-Fi的方法&#xff1a; 检查信号强度&#xff1a…

【论文格式】同步更新中

1横向和纵向坐标的坐标密度不能太大&#xff0c;显示太多看起来不好看&#xff0c;本课题组采用emf&#xff0c;目前使用页面内紧凑&#xff0c;600dpi 2Force(kN):k小写 3涉及到变量的&#xff0c;变量本身斜体

cesium中的CallbackProperty

Cesium中的CallbackProperty函数解析 在Cesium中&#xff0c;CallbackProperty是一个非常有用的特性&#xff0c;它允许开发者动态更新实体&#xff08;Entity&#xff09;的属性&#xff0c;例如位置、方向、高度等。这种动态更新的能力使得Cesium在处理与时间相关的数据时变…

win10 docker启动报错virtual machine platform not enabled

Docker启动报错virtual machine platform not enabled。原因是windows未启动虚拟化平台。 跟着下面的操作基本都能解决问题。 1.打开控制面板 2.在启用或关闭windows功能中开启Hyper-V和虚拟机平台 这个虚拟机平台也一定要勾选&#xff0c;我看晚上很多帖子是没说需要勾选这个…

【jvm】C1编译器和C2编译器的区别

目录 1. 说明2. 主要特点2.1 C1编译器2.2 C2编译器 3. 编译过程与优化策略3.1 C1编译器3.3 C2编译器 4. 分层编译与协作机制5. 性能影响与选择 1. 说明 1.JVM&#xff08;Java虚拟机&#xff09;中的C1编译器和C2编译器是两种不同的即时编译器&#xff08;JIT Compiler&#x…

【人工智能】使用Python实现序列到序列(Seq2Seq)模型进行机器翻译

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 序列到序列(Sequence-to-Sequence, Seq2Seq)模型是解决序列输入到序列输出任务的核心架构,广泛应用于机器翻译、文本摘要和问答系统等自然语言处理任务中。本篇文章深入介绍 Seq2Seq 模型的原理及其核心组件(…

【弓箭傳說 2 角色遊戲攻略】—詳細指南

《弓箭傳說2》是一款經典的Roguelike風格手遊&#xff0c;玩家將透過獨特的技能組合和角色選擇&#xff0c;挑戰複雜的關卡和強大的敵人。弓箭傳說 2 儲值 - 本攻略將從角色選擇、技能搭配、裝備強化及天賦升級等方面&#xff0c;全面解讀如何在遊戲中取得最佳表現。 一、遊戲…

Webpack 的构建流程

Webpack 的构建流程可以概括为以下几个步骤&#xff1a; 1. 初始化&#xff1a; Webpack 读取配置文件&#xff08;webpack.config.js&#xff09;&#xff0c;合并默认配置和命令行参数&#xff0c;初始化Compiler对象。 2. 构建依赖图&#xff1a; 从入口文件开始递归地分…

set up RAGFlow on your Mac

个人思考&#xff1a;这些仅仅是工具&#xff0c;和人的思维实际还是有很大差距。 可能是我认知片面&#xff0c;你需要投喂大量的内容给它&#xff0c;它自己其实并不会思考&#xff0c;只是从它的认知里告诉它他知道的东西。举个不太巧当的例子&#xff0c;和以往的方式恰恰相…

【0351】Postgres内核 Open WAL segment(包含 WAL 位置 ‘RecPtr’)(2 - 4)

上一篇: 文章目录 1. 打开 WAL Segment2. Standby mode 由一个 状态机(state machine)实现2.1 何处获取 WAL 文件?2.1.1 XLogSource2.1.2 从所选源(XLogSource )读取 XLOG2.1.2.1 walreceiver 运行状态 ?2.1.3 readFile(XLOG 文件句柄)1. 打开 WAL Segment 在经过前…

Java对象与XML互相转换(xstream)

依赖 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.18</version></dependency> 实体类 package com.itheima.util;import lombok.AllArgsConstructor; import lom…

数字IC后端实现之PR工具中如何避免出现一倍filler的缝隙?

在数字IC后端实现中&#xff0c;由于有的工艺foundary不提供Filler1&#xff0c;所以PR工具Innovus和ICC2在做标准单元摆放时需要避免出现两个标准单元之间的缝隙间距是Filler1。为了实现这个目的&#xff0c;我们需要给PR工具施加一些特殊的placement constraint&#xff08;典…

跟我学C++中级篇——通信的数据的传递形式

一、通信的数据传递 在开发程序中&#xff0c;无可避免的会进行数据的传递。这种传递方式有很多种&#xff0c;字节流、消息、Json、参数以及对象甚至可能的方法。那么在传递这些数据时&#xff0c;如何正确的采用更合适的方法&#xff0c;就成为了一个设计的首选的问题。 二…

C# HandyControl 官方示例 保姆级从0到1搭建学习流程

HandyControl 保姆级从0到1官网示例搭建学习流程 GitHub https://github.com/HandyOrg/HandyControl 技术交流 https://join.slack.com/t/handycontrol/shared_invite/zt-sw29prqd-okFmRlmETdtWhnF7C3foxA 码云 https://gitee.com/handyorg/HandyControl/ 中文文档 http…