nginx map配置根据请求头不同分配流量到不同后端服务,nginx版本为:nginx version: nginx/1.17.9
配置nginx.conf文件
http {
...
map_hash_bucket_size 64;
map $http_x_group_env $svc_upstream {
default zxl-test-splitflow-old-version;
~*old zxl-test-splitflow-old-version;
~*new zxl-test-splitflow-new-version;
}
upstream zxl-test-splitflow-old-version {
server 10.168.173.29:8080 max_fails=0 fail_timeout=0;
}
upstream zxl-test-splitflow-new-version {
server 10.168.177.171:8080 max_fails=0 fail_timeout=0;
}
server {
listen 8998;
server_name aa.hc.harmonycloud.cn;
location /testdemo/test {
proxy_pass http://$svc_upstream;
}
}
}
当在电脑上hosts文件里配置了aa.hc.harmonycloud.cn域名解析后,访问http://aa.hc.harmonycloud.cn:8998/testdemo/test时(即server的server_name和listen、location的配置),nginx将会把请求转发到http://$svc_upstream
,这个$svc_upstream
具体是什么,就是通过map配置来赋值的。这里map配置如下:
map $http_x_group_env $svc_upstream {
default zxl-test-splitflow-old-version;
~*old zxl-test-splitflow-old-version;
~*new zxl-test-splitflow-new-version;
}
其中$http_x_group_env
可以是nginx内置变量,也可以是自定义的header的key、请求参数名;$svc_upstream
即为自定义变量名。这里的配置含义为:当请求头里的x-group-env的值为old时,$svc_upstream
被赋值为zxl-test-splitflow-old-version;当请求头里的x-group-env的值为new时,$svc_upstream
被赋值为zxl-test-splitflow-new-version;默认赋值为zxl-test-splitflow-old-version;
(其中正则表达式如果以 “~” 开头,表示这个正则表达式对大小写敏感。以 “~*”开头,表示这个正则表达式对大小写不敏感,很多时候map使用正则匹配)。而zxl-test-splitflow-new-version和zxl-test-splitflow-old-version表示两个upstream名称。
因此nginx将会把请求转发到http://$svc_upstream
,这里的$svc_upstream
会被替换为upstream的名称,最终将得到upstream中的后端服务IP和Port。
注意:如果我们自定义header为X-Real-IP,nginx获取该header时需要这样:$http_x_real_ip
; (一律采用小写,而且前面多了个http_,且中间用_替换)
3、分流测试
以下测试是用springboot写了两个demo服务,即url访问方式一样,都是GET请求,URI为/testdemo/test,只是响应内容有区别。将两个demo服务做成docker镜像部署到了kubernetes集群里,请求通过ingress-nginx转发到后端demo服务。
当请求头里加x-group-env为new时,访问后端打印出的是I am new version
当请求头里加x-group-env为old时,访问后端打印出的是I am old version
最终通过请求头不同实现了将流量分配到不同的后端服务。
将请求头的key变为X-Group-Env,value变为OLD或者NEW也没关系: