首页 > 中国高端品牌网 > 数据 > 内容页

全球即时:灵活应用Nginx Map:实战经验与实用方法

2023-04-19 02:14:54 来源:哔哩哔哩

Map 介绍

map 指令是 Nginx 配置文件中的一个指令,它用于在请求处理期间创建变量,并根据指定的键值对映射关系进行值的映射。它可以用于动态地生成配置项的值,例如根据请求的 URL、请求头、查询参数等信息来生成不同的值。


(资料图片仅供参考)

map 指令的语法如下:

map $variable $new_variable {    key value;    key value;    ...    default value;}

其中,$variable 是要映射的变量,可以是任何有效的 Nginx 变量,如 $uri、$args、$http_host 等;$new_variable 是映射后的新变量名,可以自定义;key 是映射的键,可以是字符串、正则表达式或者变量;value 是映射的值,可以是字符串、变量或者表达式;default 是默认值,当没有匹配到任何键时使用。

map 指令的作用是将 $variable 的值根据键值对映射关系映射到 $new_variable 上,并且这个映射是在配置文件加载时进行的,不会在请求处理期间进行计算。一旦映射关系确定,映射的值会保存在 $new_variable 中,并可以在配置文件中的其他地方使用。

map 指令可以用于许多场景,例如根据请求的路径生成重写规则、根据请求头判断是否启用缓存、根据查询参数配置不同的后端服务等。它为 Nginx 提供了更加灵活和动态的配置选项。下面看几个经典使用场景。

巧用map实现Nginx stream基于源IP做路由负载

业务方新加了一个业务网关,上线前需要做个验证,把来源ip为27.38.x.255和116.30.x.170访问用户路由到新new_gateway做验证,其他的继续走old_gateway。

stream {       log_format  basic   '$time_iso8601 $remote_addr '                        '$protocol $status $bytes_sent $bytes_received '                        '$session_time $upstream_addr '                        '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';    access_log   /var/log/nginx/stream.log  basic buffer=1k flush=5s;     upstream old_gateway {        server 10.6.11.86:8080;    }    upstream new_gateway {        server 10.6.11.86:80;    }    map $remote_addr $backend_svr {        "27.38.x.255" "new_gateway";        "116.30.x.170" "new_gateway";        default "old_gateway";    }        server {        listen 8080;        proxy_connect_timeout 2s;        #ssl_preread on;        #proxy_protocol on;        proxy_pass $backend_svr;    }}

要基于Nginx变量($cookie_uin)限制请求数

现在有个uri(/v3/aggregate/broker/trade/NewIpoFinancing)要基于Nginx变量($cookie_uin)限制请求数.

1 限制每个uin 2s一个请求,如果$cookie_uin 为空,则给一个默认的uin

//在Nginx主配置文件添加如下配置http {    include       mime.types;    ...    map $cookie_uin $my_cookie_uin {        default $cookie_uin;        '-' 10010;        '' 10010;    }    limit_req_zone $my_cookie_uin zone=limit_per_uin:10m rate=30r/m;     ...  }// uri 接口配置文档location ~ ^/v3/aggregate/broker/trade/NewIpoFinancing {    limit_req zone=limit_per_uin burst=3 nodelay;    include /etc/nginx/vhost/common/cors.conf;    proxy_pass http://access_trade3;}

2 限制每个uin 2s一个请求,如果$cookie_uin 为空,返回403

//在Nginx主配置文件添加如下配置http {    include       mime.types;    ...    map $cookie_uin $limit_key {        default 0;        '-' 1;        '' 1;    }    limit_req_zone $cookie_uin zone=limit_per_uin:10m rate=30r/m;     ...  }// uri 接口配置文档location ~ ^/v3/aggregate/broker/trade/NewIpoFinancing {    if ($limit_key = 1) {        return 403;    }    limit_req zone=limit_per_uin burst=3 nodelay;    include /etc/nginx/vhost/common/cors.conf;    proxy_pass http://access_trade3;}

3 限制每个uin 2s一个请求,如果$cookie_uin 为空,返回403, 如果是vip uin不做限制

//在Nginx主配置文件添加如下配置http {    include       mime.types;    ...    map $cookie_uin $limit_key {        default 0;        '-' 1;        '' 1;        '666666' 10;        '666667' 10;        '666668' 10;    }    limit_req_zone $cookie_uin zone=limit_per_uin:10m rate=30r/m;    ...  }// uri 接口配置文档location ~ ^/v3/aggregate/broker/trade/NewIpoFinancing {    if ($limit_key = 1) {        return 403;    }    #vip uin    error_page 410 = @nolimit;    if ($limit_key = 10) {        return 410;    }    limit_req zone=limit_per_uin burst=3 nodelay;    include /etc/nginx/vhost/common/cors.conf;    proxy_pass http://access_trade3;}location @nolimit {    include /etc/nginx/vhost/common/cors.conf;    proxy_pass http://access_trade3;}

利用Nginx Map实现正向代理动态切换

map $host $idc {        default lg;   }       map $idc $backend_4430_svr {        default   https://$host$request_uri;        lg        https://$host$request_uri;        kx        http://10.0.x.136:4430;    }        map $idc $backend_8880_svr {        default   http://$host$request_uri;        lg        http://$host$request_uri;        kx        http://10.0.x.13:8880;    }        map $idc $backend_4480_svr {        default   $http_PROT://$http_DN:$http_Port;        lg        $http_PROT://$http_DN:$http_Port;        kx        http://10.0.x.13:4480;    }        server {        listen       8880;        location / {            resolver 127.0.0.1;            proxy_pass  $backend_8880_svr;            proxy_set_header Host $host;            proxy_set_header X-Real-IP  $remote_addr;            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;       }    }       server {        listen       4480;        location / {            resolver 127.0.0.1;            proxy_pass  $backend_4480_svr;            proxy_set_header Host $http_DN;            proxy_connect_timeout 10s;            proxy_read_timeout 20s;       }    }    server {        listen       4430;        location / {            resolver 127.0.0.1;            proxy_pass  $backend_4430_svr;            proxy_set_header Host $host;            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;       }    }

根据请求头中的PROT、DN和Port字段的值,将请求转发到不同的后端服务器。其中,PROT字段表示请求的协议(http或https),DN字段表示请求的域名,Port字段表示请求的端口号。

根据配置文件中的map指令,将$host(请求头中的域名)映射为$idc,然后根据$idc的值将请求转发到相应的后端服务器。

具体的转发规则如下:

当$idc的值为ns时,将请求转发到$backend_4430_svr,并将请求头中的Host字段和X-Forwarded-For字段传递给后端服务器。

当$idc的值为ft时,将请求转发到$backend_8880_svr,并将请求头中的Host字段、X-Real-IP字段和X-Forwarded-For字段传递给后端服务器。

当$idc的值为其他值时,将请求转发到$backend_4480_svr,并将请求头中的Host字段、PROT字段、DN字段和Port字段传递给后端服务器。

请求的具体转发地址是根据配置文件中的map指令和后端服务器的配置进行拼接的,例如https://$host$request_uri表示将请求转发到https协议下的当前域名,并保留原始请求的URI路径。

因此,当使用以下命令发送请求时:

curl -v -H 'content-type: aplication/json' -H 'PROT: https' -H 'DN: www.test.com' -H 'Port: 8899' -d '{"data": "xxxx", "body":"1"}'  http://nginx_ip:4480/test/uri

请求将被转发到$backend_4480_svr,并根据请求头中的PROT、DN和Port字段的值拼接成后端服务器的地址,同时将请求头中的Host字段、PROT字段、DN字段和Port字段传递给后端服务器。具体的转发地址会根据配置文件中的map指令和后端服务器的配置进行动态生成。

关键词:
x 广告
x 广告