基于Nginx实现灰度发布,让不同用户访问不同的服务

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

很多时候项目上线,需要进行一次生产测试,但是呢又不想用户访问最新的接口服务,看到最新的内容。于是需要有一个叫白名单的家伙来控制流量。

具体实现方式呢,有很多种,在介绍nginx实现之前,先说说大致的方案。

方案一

这点有争论,到底是前端控制还是后台控制呢?

后台控制

不要争了,这种事情还是交给后端来做吧。

  1. 后台写白名单配置文件,如果是那种配置中心的服务架构,那么这种情况不需要重启服务干预,它会自动获取白名单用户,那么也唯有白名单用户才能访问最新的服务,其他用户则无感知。

  2. 反过来如果没有配置中心,那么会出现情况:每增删白名单一次,就需要重启服务一次才能生效,很显然这种办法不是很灵活。

  3. 再来一种就是客户端版本控制,也就是说新服务需要指定的客户端版本才能访问,惯例最新版本,那么内测人员可以升级成最新客户端版本,而其他用户则没有升级提示也就无法访问。

  4. 还有一种吗?有就是接下来要做事情,通过nginx来控制。

方案二

Nginx (engine x) 是一个高性能的HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。

其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。

Nginx是一款轻量级Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东新浪网易腾讯淘宝等。

---- 来自百度百科

  1. 同过ip策略来限制分流,也就是说只有指定的ip才能访问,但是这个做法需要第三个节点来控制

假如原来是双节点A、B,那么如何通过ip控制访问新发布的服务呢?

image.png

第一个问题,ip来自哪里?

a> 数据库,如果我们会记录用户常用的ip地址,那么就可以筛选一批出来,当然目前而言可能很多情况ip都是动态发生改变的。

b> 限制内网就可以,也就是说上线后,只允许公司网络访问新服务,而要访问旧服务就需要自己切换自己的流量。

第二个问题,验证完之后呢?

a> C节点需要释放,或者放开ip限制;总归是需要操作nginx两次。

b> 可以不用释放,在做服务器容灾的时候,当其他节点服务器崩溃,可以迅速启用备用服务器,保证用户能正常访问。

# 定义两个服务节点

upstream myservername{

# ip_hash;

server 127.0.0.1:9100; # 不一定是本机,而是其他服务器的内网地址

server 127.0.0.1:9102;

}

server {

listen 80;

server_name localhost;


location / {

# ()不要靠着if,假设远程调用服务ip地址,等于 192.168.2.188,则重定向到http://$host/jforum;否则继续访问当前/根路径协议页面

if ( $remote_addr = '192.168.2.188' ){

rewrite ^/(.*)$ http://$host/jforum permanent;

}

root /data/www/html/dist/flaget;

index index.html index.htm;

try_files $uri $uri/ /index.html;

}


# 正常nginx本地访问localhost/jforum即可

location ^~ /jforum {

proxy_pass http://127.0.0.1:8080; # 这是第三个服务节点

proxy_redirect off;

proxy_set_header Host $host;

proxy_set_header Http-referer $http_referer;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}
复制代码

效果演示

本来是访问localhost默认打开是协议页面的,也就是没有加入if条件判断

image.png

加上条件判断之后访问同一个地址:http://localhost,页面跳转就相当于直接访问http://localhost/jforum地址一样

image.png

这是一种处理方式,但是要看服务来控制,否则请求后台服务就不知道去哪里了,一般建议在当前需要控制的location块中判断或者在location块之外判断并预设值即可

set $myservername 127.0.0.1:9100;

# 这样设置,也就是排除本机

if ($remote_addr != '192.168.2.188'){

set $myservername 127.0.0.1:8080;

}

# 其他ip的客户端访问就会正常,本机访问服务器异常

location ^~/jforum {

proxy_pass http://$myservername; # 这个意思就更简单了,如果前面的if条件判断正确了,那么$myservername 就是新值,否则不变。

proxy_redirect off;

proxy_set_header Host $host;

proxy_set_header Http-referer $http_referer;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}
复制代码

这样就可以测试,在不同ip的客户端访问http://localhost/jforum会是响应啥了。

总结

nginx都是通过反向代理实现白名单访问新服务;这也是比较实用的解决办法,也可以通过不同的设置来做到服务器容灾处理。

  1. nginx还有很多功能需要不断学习和实践,才能掌握它的强大;

  2. 在多年之前也有接触过关于白名单的设置,那时总觉得太遥远,才没有虚心向运维大佬请教。

猜你喜欢

转载自juejin.im/post/7019458217855942692