灰度发布详细架构图&测试方案
https://www.processon.com/diagraming/5b532fb8e4b053a09c0f7e16
https://www.processon.com/diagraming/5b532471e4b0f8477d8d901c
图为整体架构图,分为fe部署块、api部署块、分流策略、升级服务、管理后台
流程如下
流程如下
1.客户端client及服务端server已存在稳定版本A
,现准备发布灰度版本B
,上线步骤:
1.QA部署版本Bserver端
代码至灰度服务器
2.OP后台操作:
版本B
的信息:包括clientUrl, 班级白名单,分流服务ip+portclient端
状态为上线,且ip+port注册到分流服务2.假设版本B灰度顺利,准备修改为全量上线
1.OP后台操作: 点击版本B的.全量.按钮,此时版本B类型变更为全量,删除白名单
2.QA部署代码至稳定版服务器集群
3.OP后台操作:点击版本B的.上线.按钮,此时删除分流服务中的ip+port映射,默认走default配置,即指向稳定服务器集群
3.假设版本B灰度不顺利,准备下线
1.OP后台操作:点击版本B的下线按钮,此时版本B状态变更下线,删除白名单,删除分流服务ip+port
如下图
[loadbalance]
Host = "127.0.0.1:9100"
新增启动命令参数,如./frontlistener -port=8088 -lbs=127.0.0.1:8081,其中port表示监听的端口,lbs为配置的nginx api组
多台服务器部署
参照单台服务器配置,只是将nginx分散到不同的服务器,配置对应的server、server_name等参数
本次针对灰度测试重点如下:
1. 灰度API组的添加、删除、查询(对应提测接口)
2. 灰度版本与API组的映射的添加、删除、查询(对应提测接口)
3. 灰度分流是否正常,在配置了1和2的路由后,对应版本的请求是否正确路由到指定后段API组(可通过API组的日志确认),默认走stable API组流程是否正确(即没有配置任何灰度的时候,是否所有版本都路由到stable API)
4. API组内部(包括stable API)根据班级取模策略路由到不同的API实例机器,比如,如果stable API组有三台API机器服务,classId=100、101和102的班级,上课的时候这三个班级应该会分散路由到三台服务器上
5. 服务器故障摘除稳定性验证,4中的API组入锅摘除非默认实例,正在这个实例上课的班级是否可以重连到另外一台机器正常上课
6. 客户端接入的流量是否均匀分散在不同nginx服务器上
nginx1配置为
grayscaler.ngx.conf 配置内容如下
map $host $lua_dir {
default "/data/www/ailua";
}
lua_package_path "/data/www/ailua/?.lua";
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
map $scheme $upstream_scheme {
default http;
'https' http;
'wss' ws;
}
lua_shared_dict _gray_ups_zone 4m;
lua_shared_dict _gray_ver_zone 4m;
upstream default_gray_upstream {
server nginx1ip:9100;
}
log_format grayscale '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$proxy_host" $upstream_addr $upstream_scheme';
server {
listen 81;
server_name nginx1ip;
rewrite ^(.*) https://aiclass.knowbox.cn$request_uri permanent;
}
server {
listen 80;
server_name nginxip1;
set $site_home_fe /data/www/aiclassfe/dist/final;
server_tokens off;
location ~ ^/grayscale/upstream/([-_a-zA-Z-0-9]+) {
access_by_lua_file $lua_dir/grayscale/access_check.lua;
content_by_lua_file $lua_dir/grayscale/upstream/$1.lua;
}
location ~ ^/grayscale/version/([-_a-zA-Z-0-9]+) {
access_by_lua_file $lua_dir/grayscale/access_check.lua;
content_by_lua_file $lua_dir/grayscale/version/$1.lua;
}
location ~ /api/ {
set $identify '';
set_by_lua_file $ups $lua_dir/grayscale/proxy_version.lua;
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass $upstream_scheme://$ups;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
rewrite ^/api/(.*)$ /$1 break;
}
location ~ .*\.(js|css|png|jpg)$ {
root $site_home_fe;
expires 1d;
}
location ~ .*\.(html)$ {
root $site_home_fe;
expires 30;
}
location / {
root $site_home_fe;
index student.html;
}
access_log /data/logs/nginx/aiclassapi/aiclass.knowbox.cn_access.log grayscale;
error_log /data/logs/nginx/aiclassapi/aiclass.knowbox.cn_error.log;
}
balancer_stable.ngx.conf配置内容如下
map $host $lua_dir {
default "/data/www/ailua";
}
lua_package_path "/data/www/ailua/?.lua";
init_worker_by_lua_file /data/www/ailua/loadbalance/nginx_init.lua;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
lua_shared_dict _balance_ups_zone 4m;
lua_shared_dict _balance_proxy_zone 128m;
upstream default_aiclass_upstream {
server 10.9.84.249:8100;
}
log_format aiclass '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$proxy_host" $upstream_addr';
server {
listen 9100;
server_name nginxip1;
location ~ ^/loadbalance/upstream/([-_a-zA-Z0-9]+) {
access_by_lua_file $lua_dir/loadbalance/access_check.lua;
content_by_lua_file $lua_dir/loadbalance/upstream/$1.lua;
}
location / {
set $identify '';
set_by_lua_file $ups $lua_dir/loadbalance/proxy_ups.lua;
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass $scheme://$ups;
}
access_log /data/logs/nginx/aiclassapi/aiclassapi_stable_access.log aiclass;
error_log /data/logs/nginx/aiclassapi/aiclassapi_stable_error.log;
}
nginx2配置
balancer_gray.ngx.conf 配置内容
map $host $lua_dir {
default "/data/www/ailua";
}
lua_package_path "/data/www/ailua/?.lua";
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
map $scheme $upstream_scheme {
default http;
'https' http;
'wss' ws;
}
lua_shared_dict _gray_ups_zone 4m;
lua_shared_dict _gray_ver_zone 4m;
upstream default_gray_upstream {
server ngixnip1:9100;
}
log_format grayscale '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$proxy_host" $upstream_addr $upstream_scheme';
server {
listen 81;
server_name nginxip2;
rewrite ^(.*) https://aiclass.knowbox.cn$request_uri permanent;
}
server {
listen 80;
server_name nginx2;
set $site_home_fe /data/www/aiclassfe/dist/final;
server_tokens off;
location ~ ^/grayscale/upstream/([-_a-zA-Z-0-9]+) {
access_by_lua_file $lua_dir/grayscale/access_check.lua;
content_by_lua_file $lua_dir/grayscale/upstream/$1.lua;
}
location ~ ^/grayscale/version/([-_a-zA-Z-0-9]+) {
access_by_lua_file $lua_dir/grayscale/access_check.lua;
content_by_lua_file $lua_dir/grayscale/version/$1.lua;
}
location ~ /api/ {
set $identify '';
set_by_lua_file $ups $lua_dir/grayscale/proxy_version.lua;
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass $upstream_scheme://$ups;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
rewrite ^/api/(.*)$ /$1 break;
}
location ~ .*\.(js|css|png|jpg)$ {
root $site_home_fe;
expires 1d;
}
location ~ .*\.(html)$ {
root $site_home_fe;
expires 30;
}
location / {
root $site_home_fe;
index student.html;
}
access_log /data/logs/nginx/aiclassapi/aiclass.knowbox.cn_access.log grayscale;
error_log /data/logs/nginx/aiclassapi/aiclass.knowbox.cn_error.log;
}
grayscaler.ngx.conf 配置内容
map $host $lua_dir {
default "/data/www/ailua";
}
lua_package_path "/data/www/ailua/?.lua";
init_worker_by_lua_file /data/www/ailua/loadbalance/nginx_init.lua;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
lua_shared_dict _balance_ups_zone 4m;
lua_shared_dict _balance_proxy_zone 128m;
upstream default_aiclass_upstream {
server grayip_online:8200;
}
log_format aiclass '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$proxy_host" $upstream_addr';
server {
listen 9200;
server_name nginx2;
location ~ ^/loadbalance/upstream/([-_a-zA-Z0-9]+) {
access_by_lua_file $lua_dir/loadbalance/access_check.lua;
content_by_lua_file $lua_dir/loadbalance/upstream/$1.lua;
}
location / {
set $identify '';
set_by_lua_file $ups $lua_dir/loadbalance/proxy_ups.lua;
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass $scheme://$ups;
}
access_log /data/logs/nginx/aiclassapi/aiclassapi_gray_access.log aiclass;
error_log /data/logs/nginx/aiclassapi/aiclassapi_gray_error.log;
}
grayscaler用于管理
grayscale有2台,当客户端发起请求的时候,通过version,进行不同的机器集群映射。
grayscale就是记录version=>集群的映射关系。
grayscale就是管理一个版本,比如1.5.0,1.5.1是映射到stable,还是gray