【问题标题】:Nginx variable with regexp带有正则表达式的 Nginx 变量
【发布时间】:2021-05-21 17:19:23
【问题描述】:

我有一个大约 40 多个节点服务器的 nginx 配置,所有这些都写成这样:

location /39/api {
    proxy_pass http://172.31.32.233:3138;
}

location /io39 {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:3138;
}

location /40/api {
    proxy_pass http://172.31.32.233:3139;
}

location /io40 {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:3139;
}

您可以看到目标节点端口随着 ID 进入 /io39 和 /39/api 路径而增加,我知道我可以使用正则表达式将数字捕获到 location 指令中,但是如何将变量增加为整数并将其用作代理的目标端口,这样我就可以为千端口编写一个唯一的指令?

谢谢!

【问题讨论】:

    标签: nginx configuration


    【解决方案1】:

    虽然在 5.5 之前的 Perl 和 PHP 中有一个 evaluation 正则表达式修饰符,但据我所知,nginx 没有任何等效项,也没有正则表达式数学是可能的。 this 回答中描述的可能技术之一。例如,您可以通过这种方式添加 30000 之类的内容(我首先使用最长的 4 位正则表达式模式,因为正则表达式匹配位置是从第一个到最后一个进行检查):

    location ~ "^/(\d{4})/api" {
        set $port 3$1;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/io(\d{4})" {
        set $port 3$1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/(\d{3})/api" {
        set $port 30$1;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/io(\d{3})" {
        set $port 30$1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/(\d{2})/api" {
        set $port 300$1;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/io(\d{2})" {
        set $port 300$1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/(\d)/api" {
        set $port 3000$1;
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/io(\d)" {
        set $port 3000$1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://172.31.32.233:$port;
    }
    

    这将为/1/api/io1(以及/01/api/io01)提供端口号30001,为/2/api/io2 提供端口号30002,依此类推,最多为39999 /9999/api/io9999 URI。

    另一种方式是使用lua-nginx-moduleOpenResty

    location ~ "^/(?<number>\d{1,4})/api" {
        set_by_lua_block $port { return ngx.var.number + 3099 }
        proxy_pass http://172.31.32.233:$port;
    }
    
    location ~ "^/io(?<number>\d{1,4})" {
        set_by_lua_block $port { return ngx.var.number + 3099 }
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://172.31.32.233:$port;
    }
    

    【讨论】:

    • 非常有用,我发现第一种方法是可行的解决方案。谢谢!
    猜你喜欢
    • 2015-03-02
    • 2017-06-25
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多