你好呀,我是赵兴晨,文科程序员。
下面的内容可以说是干货满满建议先收藏再慢慢细品。
今天,我想与大家深入探讨一个我们日常工作中不可或缺的话题——灰度环境。你是否在工作中使用过灰度环境?如果是,你的使用体验如何?
俗话说得好:“不想成为架构师的Java程序员,不是一个好的SRE。(Site Reliability Engineer,即网站可靠性工程师)”这句话看似是一句玩笑话,但是它道出了一个程序员不断追求技术深度与广度的重要性。
在日常工作中,我们不仅要精通Java,还需要掌握运维和前端技术等多方面技能,而灰度环境的构建与管理正是其中的关键一环。
那么什么是灰度发布呢?
灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB Test 就是一种灰度发布。 让一部分用户继续使用环境A, 一部分用户开始使用环境B,如果用户对环境B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到环境B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现问题并及时调整,以保证其小范围的影响度。
常见的灰度发布的方式
Nginx + Lua 实现灰度
这个说来话长,涉及到的内容太多,我在做技术选型的时候直接给这个方案pass掉了,这里就不做过多赘述。
基于 cookie 实现灰度
根据查询cookie键为version的值,如果cookie值为gray,则转发到linux_gray(灰度环境),cookie的值都不匹配的情况下,默认走linux_prod(生产环境)。
举个例子:
两个后端应用服务器分别定义为
# 灰度环境
linux_gray 10.0.0.60:10001
# 生产环境
linux_prod 10.0.0.61:10001
使用map指令实现
在Nginx里面配置一个映射,$COOKIE_version 可以解析出Cookie 里面的 version 字段, $group 是一个变量, {} 里面是映射规则。
如果一个 version为gray 的用户来访问,$group 就等于linux_gray。在 server 里面使用就会代理到http://linux_gray 上。
否则,$group 就等于 linux_prod。在 server 里面使用就会代理到 http://linux_prod 上。Cookie 值都不匹配的情况下默认走 linux_prod 所对应的服务器。
以下👇是基于cokkie实现灰度的Nginx配置参考。
# 灰度环境
upstream linux_gray {
server 10.0.0.60:10001;
}
# 生产环境
upstream linux_prod {
server 10.0.0.61:10001;
}
# 后端服务
map $COOKIE_version $group {
~*gray$ linux_gray;
default linux_prod;
}
# 前端静态资源
map $COOKIE_version $grouppath {
~*gray$ /web/staticGray/;
default /web/staticProd/;
}
server {
listen 80;
server_name linuxtest.com;
access_log logs/linux.log main;
# 后端服务
location /server/test {
# 进入灰度环境增加响应标识
if ( $COOKIE_version ~* "gray$" ){
add_header version gray always;
}
# rewrite解决 /test丢失问题
rewrite ^/server/(.*) /$1 break;
proxy_pass http://$group;
}
# 静态资源
location /serverweb {
if ( $COOKIE_version ~* "gray$" ){
add_header version gray always;
}
alias $grouppath;
try_files $uri $uri/ /index.html;
index index.html;
}
}
根据用户访问的IP 实现灰度
nginx 对用户的IP进行分流,将符合分流规则的用户IP指到linux_gray(灰度环境),其余的指到 linux_prod(生产环境)
举个例子:
两个后端应用服务器分别定义为
# 灰度环境
linux_gray 10.0.0.60:10001
# 生产环境
linux_prod 10.0.0.61:10001
跟cookie的差不多 也是使用map指令实现的,但需要获取用户的真实IP地址。
# 灰度环境
upstream linux_gray {
server 10.0.0.60:10001;
}
# 生产环境
upstream linux_prod {
server 10.0.0.61:10001;
}
# 后端服务
map $remote_addr $group {
# 只允许用户ip为10.0.0.75的用户访问灰度环境
# 也可以设置成ip段 ~*^10\.0\.0\.(.*?)$
~10.0.0.75 linux_gray;
default linux_prod;
}
# 前端静态资源
map $remote_addr $grouppath {
~10.0.0.75 /web/staticGray/;
default /web/staticProd/;
}
server {
listen 80;
server_name linuxtest.com;
access_log logs/linux.log main;
# 获取用户真实IP
set_real_ip_from 127.0.0.1; # 真实服务器上一级代理的IP地址或者IP段,可以写多行
real_ip_header X-Forwarded-For; # 从哪个header头检索出要的IP地址
real_ip_recursive on; #递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP
# 后端服务
location /server/test {
# 进入灰度环境增加响应标识
if ( $remote_addr ~* "10.0.0.75" ){
add_header version gray always;
}
# rewrite解决 /test丢失问题
rewrite ^/server/(.*) /$1 break;
proxy_pass http://$group;
}
# 静态资源
location /serverweb {
if ( $remote_addr ~* "10.0.0.75" ){
add_header version gray always;
}
alias $grouppath;
try_files $uri $uri/ /index.html;
index index.html;
}
# 测试用户访问获取用户IP
location /iptest {
return 200 $remote_addr;
}
}
上面这三种方案就是当时我做技术选型能够搜集到的方案, 基于cookie实现灰度会出现好多问题,不太符合现有系统:
1、获取cookie的时机问题,如默认用户第一次进入到系统,需要判断该用户是否是灰度用户,如果是灰度用户下次请求会携带cookie,这样前端静态资源第一次进入到的是生产环境,需要重新刷新才能进入到灰度环境,对用户不太友好。
2、如果灰度环境出现问题,需要回滚,回滚后无法保证用户实时切换回生产环境,因为只有用户登录的时候才会确定该用户是否是灰度用户,如果灰度用户在使用中,没有重新登录,会一直在灰度环境,除非强制将用户踢下线,提示用户重新登录,这样对用户体验也不友好。
所以基于以上的两个问题,最终决定选用基于用户IP来实现灰度发布。
基于用户IP实现灰度的核心所在是获取用户真实IP,并根据用户的真实IP特征来决定进入灰度的规则,IP规则可以是IP段。
以上就是我个人的一些思考,如果有不正确的地方,欢迎大家在文章底部留言指正。
如果你是第一次接触Centos7、Nginx建议看一下我之前的文章:
扫描下方👇二维码关注我,可查看相关知识点干货!
最后,我想说的是:点赞和分享不仅仅是一种美德,更是对未来美好生活的投资。愿每一个点在看的朋友,未来都能收获满满的幸福和成功!
你好,我是赵兴晨,一名文科程序员。我期待在文章下方看到你的留言,让我们一起交流,共同进步。