zoukankan      html  css  js  c++  java
  • nginx map配置根据请求头不同分配流量到不同后端服务

    正文

    最近在做一个需求开发:根据请求后的不同,nginx将请求分发到不同的后端服务;需要修改kubernetes的ingress-nginx-controller的源码,调试的时候遇到了挺多问题,写出来,有需要的老铁可以参考。具体方案就不说了,只说一下nginx配置这一块。

    首先贴出组件版本:
    ingress-nginx-controller的版本为0.9-beta.18,可以在github上找到开源的项目源码:

    nginx map配置根据请求头不同分配流量到不同后端服务
    nginx版本为:nginx version: nginx/1.13.7

    map配置的一个报错:

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

    当nginx -tc /etc/nginx/nginx.conf测试配置正确与否时报错如下:

    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
    

    在这里插入图片描述

    解决:

    这是因为首次调用map时会隐式设置map_hash_bucket_size,即在nginx中map后写map_hash_bucket_size相当于设置了两次map_hash_bucket_size,如:

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

    因此可以在map之前设置它,如下所示。

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

    所以include map配置也应该放到设置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三个配置文件,最终对nginx生效的配置应该是这样的:

    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;
    (其中正则表达式如果以 “~” 开头,表示这个正则表达式对大小写敏感。以 “~*”开头,表示这个正则表达式对大小写不敏感)。而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_,且中间用_替换)

    测试

    当请求头里加x-group-env为new时,访问后端打印出的是I am new version
    在这里插入图片描述

    当请求头里加x-group-env为old时,访问后端打印出的是I am old version
    在这里插入图片描述

    最终通过请求头不同实现了将流量分配到不同的后端服务。

    将请求头的key变为X-Group-Env,value变为OLD或者NEW也没关系:
    在这里插入图片描述

    在这里插入图片描述



    本公众号免费提供csdn下载服务,海量IT学习资源,如果你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程IT相关资源。


    扫码关注,精彩内容第一时间推给你

    image

  • 相关阅读:
    Android Studio 活动启动模式
    Android Studio 活动的生命周期
    OA表单制作(致远)
    打开excel打印时报“不能使用对象链接和嵌入”
    C#面对对象之封装、继承、多态的简单理解
    C#上手练习7(构造方法语句)
    C#上手练习7(方法语句2)
    C#上手练习6(方法语句1)
    C#上手练习5(GOTO语句)
    C#上手练习4(Break、CONITINUE语句)
  • 原文地址:https://www.cnblogs.com/liabio/p/11723807.html
Copyright © 2011-2022 走看看