V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
LeeReamond
V2EX  ›  NGINX

nginx 想针对不同 API 限制不同请求频次应该怎么写?

  •  
  •   LeeReamond · 2022-02-01 10:02:03 +08:00 · 3422 次点击
    这是一个创建于 807 天前的主题,其中的信息可能已经有所发展或是发生改变。

    配置方式:前后分离,nginx 分发静态文件,然后将 /api/路由反向代理到后端,前端无跨域。

    需求:后端 api 很多,想要使用 nginx 的限频功能,但是不同 api 频率不一样。

    现在的写法

    #上文省略
    location ^~ /api/ {
    
        proxy_pass http://127.0.0.1:3333;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          
        limit_req zone=allips burst=20 nodelay;
    }
    

    现在的写法就是全路由统一反向代理,然后公用一个 limit_req ,比如如果有/api/a1?=.../api/b2?=...这两个 api ,是否 nginx 上需要分别设置各自的路由,各自的反向代理,和各自的 limit_req 的 zone ?如果 api 特别多的话是不是 zone 增多会导致内存爆炸啊。。

    12 条回复    2022-02-03 13:16:33 +08:00
    des
        1
    des  
       2022-02-01 10:09:25 +08:00 via iPhone
    用 map 应该可以
    ilylx2008
        2
    ilylx2008  
       2022-02-01 11:31:23 +08:00
    来个中间件
    gstqc
        3
    gstqc  
       2022-02-01 11:47:12 +08:00 via Android
    规则不多就多搞几个 location 和 zone
    zone 的计数器占不了多少内存
    LeeReamond
        4
    LeeReamond  
    OP
       2022-02-01 11:54:39 +08:00
    @gstqc 规则比较多,复写能工作但我感觉这好像不是正确的配置方式。另外一个问题是使用 limit_req 功能是不是就不能使用 cf 代理了
    allenforrest
        5
    allenforrest  
       2022-02-01 12:58:28 +08:00
    类似这样?

    limit_req_zone $request_uri zone=addr2:50m rate=10r/s;
    limit_req zone=addr2 burst=20 nodelay;
    limit_req_status 503;
    adoal
        6
    adoal  
       2022-02-01 12:59:43 +08:00 via iPhone
    靠纯 nginx 的配置可以做到,不过麻烦,不如上一个 API 网关,kong 或者 apisix
    learningman
        7
    learningman  
       2022-02-01 13:08:41 +08:00
    location 块可以重复生效的吧,limit 写在具体的 block 里行不
    ryd994
        8
    ryd994  
       2022-02-01 13:19:19 +08:00 via Android
    5 楼的思路是对的。但是第一行忘了加入$binary_remote_addr ,结果就是整个 url 不论 IP 加在一起限速。也没有拆分前缀,往 uri 加额外字符就可以绕过了。要用的话你可以在 location 里用 regex match 然后用 named capture ,捕捉 url 的第一小节。

    cf 代理可以用,cf 会设置 x-forwarded-for 和 client-ip ,用好 ngx_http_realip_module ,只信任来自 cloudflare 的 client ip 即可。
    ryd994
        9
    ryd994  
       2022-02-01 13:22:11 +08:00 via Android
    还有,如果 API 不多的话可以用嵌套 location 。这样就不应反复写代理配置,每个 location 里再写一遍 limit 即可。

    还有,你这 location 写的什么玩意?/api/这不就是固定匹配,用什么 regex ?(当然你按我上面说的话那还是得用 regex 去捕捉 api 名称)
    wellsc
        10
    wellsc  
       2022-02-01 13:33:52 +08:00 via iPhone
    ng 受限于单点,上 openresty lua redis 吧
    ManjusakaL
        11
    ManjusakaL  
       2022-02-01 14:35:46 +08:00 via iPhone
    直接上个 openresty 系列的网关吧
    youyoumarco
        12
    youyoumarco  
       2022-02-03 13:16:33 +08:00
    apisix 走起
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5944 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 06:17 · PVG 14:17 · LAX 23:17 · JFK 02:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.