前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nginx根据请求头分流到不同后端服务

nginx根据请求头分流到不同后端服务

作者头像
我的小碗汤
发布2019-03-11 15:56:59
6.1K3
发布2019-03-11 15:56:59
举报
文章被收录于专栏:我的小碗汤

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

首先贴出组件版本:

ingress-nginx-controller的版本为0.9-beta.18,可以在github上找到开源的项目源码,目前已经更新到了0.22.0版本,贴出开源地址:

https://github.com/kubernetes/ingress-nginx/releases

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

主要是三个问题:

1、map配置的报错

nginx.conf文件部分如下:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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

代码语言:javascript
复制
server {
  listen 8998;  
  server_name aa.hc.harmonycloud.cn;  
  location /testdemo/test {  
    proxy_pass http://$svc_upstream;  
  }
}

ingressgroup-upstream.conf

代码语言:javascript
复制
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测试配置正确与否时报错如下:

代码语言:javascript
复制
Error: exit status 1nginx: [emerg] "map_hash_bucket_size" directive is duplicate in /etc/nginx/nginx.conf:60nginx: configuration file c test failed

解决:

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

代码语言:javascript
复制
http {  
  ...    map $status $_status {      
    default 42;    
  }    
  map_hash_bucket_size 64;    
...}

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

代码语言:javascript
复制
http {  
  map_hash_bucket_size 64;    
  ...    
  map $status $_status {      
    default 42;    
  }    
...}

所以include map配置也应该放到设置map_hash_bucket_size之后:

代码语言:javascript
复制
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;
}

2、map配置说明

通过上面的include三个配置文件,最终对nginx生效的配置应该是这样的:

代码语言:javascript
复制
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配置如下:

代码语言:javascript
复制
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_,且中间用_替换)

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也没关系:

• end •

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 进击云原生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档