nginx map配置根據(jù)請(qǐng)求頭不同分配流量到不同后端服務(wù)

最近在做一個(gè)需求開發(fā):根據(jù)請(qǐng)求后的不同,nginx將請(qǐng)求分發(fā)到不同的后端服務(wù);需要修改kubernetes的ingress-nginx-controller的源碼,調(diào)試的時(shí)候遇到了挺多問題,寫出來,有需要的老鐵可以參考。具體方案就不說了,只說一下nginx配置這一塊。

首先貼出組件版本:
ingress-nginx-controller的版本為0.9-beta.18,可以在github上找到開源的項(xiàng)目源碼:

nginx map配置根據(jù)請(qǐng)求頭不同分配流量到不同后端服務(wù)
nginx版本為:nginx version: nginx/1.13.7

map配置的一個(gè)報(bào)錯(cuò):

nginx.conf文件部分如下:

http {
    
    include /etc/nginx/conf.d/server-map.d/*-map.conf;
    include /etc/nginx/conf.d/*-upstream.conf;
    include /etc/nginx/conf.d/server-map.d/*-server.conf;

    ....

    map_hash_bucket_size 64;

    ....
}

在/etc/nginx/conf.d/server-map.d/目錄下的flow-ppp-map.conf:

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;
}

flow-ppp-server.conf

server {
    listen 8998;
    server_name aa.hc.harmonycloud.cn;
    location /testdemo/test {
        proxy_pass http://$svc_upstream;
    }
}

ingressgroup-upstream.conf

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;
}

當(dāng)nginx -tc /etc/nginx/nginx.conf測試配置正確與否時(shí)報(bào)錯(cuò)如下:

Error: exit status 1
nginx: [emerg] "map_hash_bucket_size" directive is duplicate in /etc/nginx/nginx.conf:60
nginx: configuration file c test failed
image.png

解決:

這是因?yàn)槭状握{(diào)用map時(shí)會(huì)隱式設(shè)置map_hash_bucket_size,即在nginx中map后寫map_hash_bucket_size相當(dāng)于設(shè)置了兩次map_hash_bucket_size,如:

http {
    ...
    map $status $_status {
        default 42;
    }
    map_hash_bucket_size 64;
    ...
}

因此可以在map之前設(shè)置它,如下所示。

http {
    map_hash_bucket_size 64;
    ...
    map $status $_status {
        default 42;
    }
    ...
}

所以include map配置也應(yīng)該放到設(shè)置map_hash_bucket_size之后:

http {
    ...

    map_hash_bucket_size 64;

    ...
    
    include /etc/nginx/conf.d/server-map.d/*-map.conf;
    include /etc/nginx/conf.d/*-upstream.conf;
    include /etc/nginx/conf.d/server-map.d/*-server.conf;
}

map配置說明:

通過上面的include三個(gè)配置文件,最終對(duì)nginx生效的配置應(yīng)該是這樣的:

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;
        }
    }
}

當(dāng)在電腦上hosts文件里配置了aa.hc.harmonycloud.cn域名解析后,訪問http://aa.hc.harmonycloud.cn:8998/testdemo/test時(shí)(即server的server_name和listen、location的配置),nginx將會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到http://$svc_upstream,這個(gè)$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內(nèi)置變量,也可以是自定義的header的key、請(qǐng)求參數(shù)名;$svc_upstream即為自定義變量名。這里的配置含義為:當(dāng)請(qǐng)求頭里的x-group-env的值old時(shí),$svc_upstream被賦值為zxl-test-splitflow-old-version;當(dāng)請(qǐng)求頭里的x-group-env的值new時(shí),$svc_upstream被賦值為zxl-test-splitflow-new-version;默認(rèn)賦值為zxl-test-splitflow-old-version;
(其中正則表達(dá)式如果以 “~” 開頭,表示這個(gè)正則表達(dá)式對(duì)大小寫敏感。以 “~*”開頭,表示這個(gè)正則表達(dá)式對(duì)大小寫不敏感)。而zxl-test-splitflow-new-version和zxl-test-splitflow-old-version表示兩個(gè)upstream名稱。

因此nginx將會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到http://$svc_upstream,這里的$svc_upstream會(huì)被替換為upstream的名稱,最終將得到upstream中的后端服務(wù)IP和Port。

注意:如果我們自定義header為X-Real-IP,通過第二個(gè)nginx獲取該header時(shí)需要這樣:$http_x_real_ip; (一律采用小寫,而且前面多了個(gè)http_,且中間用_替換)

測試

當(dāng)請(qǐng)求頭里加x-group-env為new時(shí),訪問后端打印出的是I am new version


image.png

當(dāng)請(qǐng)求頭里加x-group-env為old時(shí),訪問后端打印出的是I am old version


image.png

最終通過請(qǐng)求頭不同實(shí)現(xiàn)了將流量分配到不同的后端服務(wù)。

將請(qǐng)求頭的key變?yōu)閄-Group-Env,value變?yōu)镺LD或者NEW也沒關(guān)系:


old
new
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容