前言
目前的需求是,根据用户的IP,让他跳转到不同的后端服务上。在后端的服务中有线上的也有新开发的内容,为了减少影响,所以需要使用灰度发布,在尽量减少线上用户的情况下,做一下灰度发布。这里我测试使用客户端的IP,也可以选择用户的ID等等。使用客户端IP做分流,也可以用到安全里,进行限制,比如我指定部分IP能够访问我的服务,其他的IP都返回一个304状态。
nginx安装
这里我就不多说了,前面已经说过nginx的安装了,可以参考:https://www.wulaoer.org/?p=295
配置nginx(用户ip)
这里使用的是map去匹配一些规则,map是有 ngx_http_map_module 模块提供的,默认nginx都会有安装,这里也就不说了,注意map的规则必须要放到http里,不能放到server中。
[root@www.wulaoer.org nginx]# vim nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
#map $http_wx_unionid $request_from_intranet {
map $remote_addr $request_ip { #这里使用map做的规则
default "true";
10.211.55.142 "false";
}
}
在http中定义的map规则是除了IP(10.211.55.142)访问nginx会生成变量$request_ip等于false以外,其他的都会把变量$request_ip等于true。我们在nginx的server中在根据变量$request_ip进行用户返回结果。
[root@www.wulaoer.org nginx]# cat conf.d/default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
if ($request_ip = "true" ) { #map的规则需要在这里进行判断
rewrite ^/(.*)$ http://www.baidu.com;
}
if ($request_ip = "false" ) {
rewrite ^/(.*)$ http://www.360.cn;
}
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
这里注意,我们的map定义的规则,需要进行一个判断,这里是在location中进行判断,如果变量$request_ip等于true会返回百度的网址信息,如果变量$request_ip等于false会返回360的信息,定义好后,我们reload一下nginx。
[root@www.wulaoer.org nginx]# /usr/sbin/nginx -s reload
至此,nginx的IP分流已经设置好了。
验证(用户ip)
我分别在两台虚拟机进行curl验证,这里注意,使用curl不会自动做301跳转,需要加一个参数"-L",如果不加"-L"不会跳转判断下的url上。
[root@wulaoer ~]# ifconfig -a|grep -o -e 'inet [0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}'|grep -v "127.0.0"|awk '{print $2}'
10.211.55.142
[root@wulaoer ~]# curl -L --head http://10.211.55.143
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.16.1
Date: Tue, 24 Mar 2020 02:17:34 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://www.360.cn
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.9
Date: Tue, 24 Mar 2020 02:18:02 GMT
Content-Type: text/html
Content-Length: 178
Connection: close
Location: https://www.360.cn
HTTP/1.1 200 OK
Server: nginx/1.2.9
Date: Tue, 24 Mar 2020 02:18:05 GMT
Content-Type: text/html
Content-Length: 74108
Connection: close
Last-Modified: Fri, 20 Mar 2020 12:35:15 GMT
ETag: "5e74b883-1217c"
Accept-Ranges: bytes
wulaoer这台机器的ip是map规则中返回变量$request_ip等于false,所以应该跳转到360。下看另外一个没有加入到map规则的IP:
[root@wolf ~]# ifconfig -a|grep -o -e 'inet [0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}'|grep -v "127.0.0"|awk '{print $2}'
10.211.55.141
[root@wolf ~]# curl -L --head http://10.211.55.143
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.16.1
Date: Tue, 24 Mar 2020 02:17:45 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Tue, 24 Mar 2020 02:18:06 GMT
Etag: "575e1f60-115"
Last-Modified: Mon, 13 Jun 2016 02:50:08 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
wolf这台机器的ip没有加入到map规则中,所以变量$request_ip等于true,返回用户百度的信息。
配置nginx(使用用户http_wx_unionid做分流)
上面使用的用户IP做的分流,这里尝试使用用户的http_wx_unionid做分流,和上面的思路是一样的,这里配置一下
[root@www.wulaoer.org nginx]# cat nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
#map $http_wx_unionid $request_from_intranet {
map $http_wx_unionid $request_ip {
default "false";
9999999 "true";
8888888 "true";
}
}
下面在server中对http_wx_unionid进行一个判断,判断的是变量$http_wx_unionid后面的$request_ip,这里的$request_ip必须要和server中判断的变量一样。$request_ip可以随意修改,两边一致即可。
[root@www.wulaoer.org nginx]# cat conf.d/default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
underscores_in_headers on;
location / {
#root /usr/share/nginx/html;
#index index.html index.htm;
if ($request_ip = "true" ) { #等于map中的$request_ip进行判断
#rewrite ^/(.*)$ http://www.baidu.com;
proxy_pass http://www.baidu.com;
}
if ($request_ip = "false" ) {
proxy_pass http://www.google.cn;
}
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
这里判断使用的不太一样了,使用IP用的rewrite,这里使用的是proxy_pass,如果使用rewrite会跳转不过去。
验证(http_wx_unionid)
我们在用户访问的时候加个参数http_wx_unionid,这样nginx才会循环map中的http_wx_unionid进行一个判断,然后根据判断进行返回。
[root@www.wulaoer.org nginx]# curl -L -v -H 'wx_unionid:8888888' http://10.211.55.143 * About to connect() to 10.211.55.143 port 80 (#0) * Trying 10.211.55.143... * Connected to 10.211.55.143 (10.211.55.143) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 10.211.55.143 > Accept: */* > wx_unionid:8888888 > < HTTP/1.1 200 OK < Server: nginx/1.16.1 < Date: Tue, 24 Mar 2020 03:32:28 GMT < Content-Type: text/html < Content-Length: 2381 < Connection: keep-alive < Accept-Ranges: bytes < Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform < Etag: "588604c8-94d" < Last-Modified: Mon, 23 Jan 2017 13:27:36 GMT < Pragma: no-cache < Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/ < <!DOCTYPE html> <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html> * Connection #0 to host 10.211.55.143 left intact [root@www.wulaoer.org nginx]# curl -L -v -H 'wx_unionid:1111' http://10.211.55.143 * About to connect() to 10.211.55.143 port 80 (#0) * Trying 10.211.55.143... * Connected to 10.211.55.143 (10.211.55.143) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 10.211.55.143 > Accept: */* > wx_unionid:1111 > < HTTP/1.1 200 OK < Server: nginx/1.16.1 < Date: Tue, 24 Mar 2020 03:32:35 GMT < Content-Type: text/html < Transfer-Encoding: chunked < Connection: keep-alive < Accept-Ranges: none < Vary: Accept-Encoding < Content-Security-Policy-Report-Only: script-src 'nonce-Bp6bcOLD0CuEzrS2QSazCQ' 'strict-dynamic' 'unsafe-eval' 'unsafe-inline' http: https:; object-src 'none'; report-uri https://csp.withgoogle.com/csp/static-on-bigtable; base-uri 'none' < Pragma: no-cache < Expires: Fri, 01 Jan 1990 00:00:00 GMT < Cache-Control: no-cache, must-revalidate < Last-Modified: Mon, 02 Dec 2019 19:30:00 GMT < X-Content-Type-Options: nosniff < X-XSS-Protection: 0 < <!DOCTYPE html> <html lang="zh"> <meta charset="utf-8"> <title>Google</title> <style> html { background: #fff; margin: 0 1em; } body { font: .8125em/1.5 arial, sans-serif; text-align: center; } h1 { font-size: 1.5em; font-weight: normal; margin: 1em 0 0; } p#footer { color: #767676; font-size: .77em; } p#footer a { background: url(//www.google.cn/intl/zh-CN_cn/images/cn_icp.gif) top right no-repeat; padding: 5px 20px 5px 0; } ul { margin: 2em; padding: 0; } li { display: inline; padding: 0 2em; } div { -moz-border-radius: 20px; -webkit-border-radius: 20px; border: 1px solid #ccc; border-radius: 20px; margin: 2em auto 1em; max-width: 650px; min-width: 544px; } div:hover, div:hover * { cursor: pointer; } div:hover { border-color: #999; } div p { margin: .5em 0 1.5em; } img { border: 0; } </style> <div> <a rel="external nofollow" target="_blank" href="https://www.wulaoer.org/wp-content/themes/begin/go.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tLmhrL3dlYmhwP2hsPXpoLUNOJmFtcDthbXA7c291cmNlaWQ9Y25ocA=="> <img src="//www.google.cn/landing/cnexp/google-search.png" alt="Google" width="586" height="257"> </a> <h1><a rel="external nofollow" target="_blank" href="https://www.wulaoer.org/wp-content/themes/begin/go.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tLmhrL3dlYmhwP2hsPXpoLUNOJmFtcDthbXA7c291cmNlaWQ9Y25ocA=="><strong id="target">google.com.hk</strong></a></h1> <p>请收藏我们的网址 </div> <ul> <li><a rel="external nofollow" target="_blank" href="https://www.wulaoer.org/wp-content/themes/begin/go.php?url=aHR0cDovL3RyYW5zbGF0ZS5nb29nbGUuY24vP3NvdXJjZWlkPWNuaHA=">翻译</a> </ul> <p id="footer">©2011 - <a rel="external nofollow" target="_blank" href="https://www.wulaoer.org/wp-content/themes/begin/go.php?url=aHR0cDovL3d3dy5taWliZWlhbi5nb3YuY24v">ICP证合字B2-20070004号</a> <script nonce="Bp6bcOLD0CuEzrS2QSazCQ"> var gcn=gcn||{};gcn.IS_IMAGES=(/images\.google\.cn/.exec(window.location)||window.location.hash=='#images'||window.location.hash=='images');gcn.HOMEPAGE_DEST='http://www.google.com.hk/webhp?hl=zh-CN&sourceid=cnhp';gcn.IMAGES_DEST='http://images.google.com.hk/imghp?'+'hl=zh-CN&sourceid=cnhp';gcn.DEST_URL=gcn.IS_IMAGES?gcn.IMAGES_DEST:gcn.HOMEPAGE_DEST;gcn.READABLE_HOMEPAGE_URL='google.com.hk';gcn.READABLE_IMAGES_URL='images.google.com.hk';gcn.redirectIfLocationHasQueryParams=function(){if(window.location.search&&/google\.cn/.exec(window.location)&&!/webhp/.exec(window.location)){window.location=String(window.location).replace('google.cn','google.com.hk')}}();gcn.replaceHrefsWithImagesUrl=function(){if(gcn.IS_IMAGES){var a=document.getElementsByTagName('a');for(var i=0,len=a.length;i<len;i++){if(a[i].href==gcn.HOMEPAGE_DEST){a[i].href=gcn.IMAGES_DEST}}}}();gcn.listen=function(a,e,b){if(a.addEventListener){a.addEventListener(e,b,false)}else if(a.attachEvent){var r=a.attachEvent('on'+e,b);return r}};gcn.stopDefaultAndProp=function(e){if(e&&e.preventDefault){e.preventDefault()}else if(window.event&&window.event.returnValue){window.eventReturnValue=false;return false}if(e&&e.stopPropagation){e.stopPropagation()}else if(window.event&&window.event.cancelBubble){window.event.cancelBubble=true;return false}};gcn.resetChildElements=function(a){var b=a.childNodes;for(var i=0,len=b.length;i<len;i++){gcn.listen(b[i],'click',gcn.stopDefaultAndProp)}};gcn.redirect=function(){window.location=gcn.DEST_URL};gcn.setInnerHtmlInEl=function(a){if(gcn.IS_IMAGES){var b=document.getElementById(a);if(b){b.innerHTML=b.innerHTML.replace(gcn.READABLE_HOMEPAGE_URL,gcn.READABLE_IMAGES_URL)}}}; gcn.listen(document, 'click', gcn.redirect); gcn.setInnerHtmlInEl('target'); </script> * Connection #0 to host 10.211.55.143 left intact
第一个返回的是百度的数据,第二个返回的是谷歌的数据,第一个的wx_unionid匹配到了,第二个没有匹配到,所以返回的数据不一样,整个实验验证成功。这里注意验证的时候参数必须使用"-V","-H"不能加参数"--head",否则参数过多过不去。
以上就是nginx通过IP进行分流的实验,如果分流的是一个集群,可以通过proxy_pass到upstream实现负载。
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏