WEB端开关系统 - wugy0103/myBlog GitHub Wiki
WEB端开关系统
背景说明:互联网产品经常存在产品升级优化、重构的情况,但并不是每一次的升级优化都能获得较好的效果,为了能够在线上验证产品的优化效果和进行数据采集分析,不修改业务代码直接线上进行异常功能下线,所以需要设计一个开关系统。
方案1:使用Json文件配置方式达到开关效果。
思路
把需要验证效果的需求记录成一个开关,配置到JSON配置文件里放在公用webserver端,用户访问页面的时候,通过接口拉取JSON文件根据JSON数据进行业务判断。
业务流程图
webserver实现
新建一个给现有所有的web端提供API的webserver,达到修改一份json文件所有前端系统都可以应用上的效果。
鉴于团队后期将会使用egg来当webserver层,所以这里也使用融合了团队的一些库的egg-demo来搭建。
1.通过ssh://[email protected]:10022/tantu-web/egg-demo.git拉取egg-demo,根据readme运行;
2.引用egg-validate 插件。
// app/config/plugin.js exports.validate = { enable: true, package: 'egg-validate', };
3.新建路由
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/api/switch/getjson', controller.switch.getjson);
};
4.新建controller
// app/controller/switch.js
'use strict';
const Controller = require('egg').Controller;
class SwitchController extends Controller {
async getjson() {
const ctx = this.ctx;
// 调用 service 获取switch数据
const data = await ctx.service.switch.getjson();
// 设置响应体和状态码
ctx.body = data;
ctx.status = 201;
}
}
module.exports = SwitchController;
5.新建service编写业务代码(读取json文件)
// app/service/switch.js
const Service = require('egg').Service;
const path = require('path'); // 系统路径模块
const fs = require('fs'); // 文件模块
class SwitchService extends Service {
async getjson() {
const file = path.join(__dirname, '/../public/data/switch.json');
const filedata = fs.readFileSync(file, 'utf-8');
return JSON.parse(filedata);
}
}
module.exports = SwitchService;
最后发布上线后设置指定域名跨域,各前端系统即可通过访问${domain}/api/switch/getjson即可获取开关配置。
用户端使用
/*根据id获取开关*/
let getSwitchState = (switchId) => {
........//根据configs判断,返回开关结果
}
/*各业务使用流程*/
if (getSwitchState("100023") == 1)
{
//开,添加处理
......
} else
{
//关,添加处理
.....
}
JSON开关配置如下(详情页改版为例)
{
"version": "v1.0.0",
"switchs": {
"201810130001": {
"switchId": "201810130001",
"switchCode": "TANTU-SW-WEB-DETAIL-0001",
"switchName": "DetailPageSW",
"switchDes": "商品详情页新旧版页面切换开关",
"switchState": 1,
"switchDefState": 0,
"whitelist": [],
"platforms": {
"mobile": {
"IOS": {
"zzc": {
"configs": [
{
"sysVersions": [
{
"start": "19",
"end": "xxx"
}
],
"appVersions": [
{
"start": "5.3.0",
"end": "xxx"
}
],
"channels": [
"zuzuCheJenkinsBuild"
],
"deviceType": [
"all"
]
}
]
},
"tantutravel": {
},
"tantumap": {
},
"wechat": {
},
"browser": {
}
},
"Android": {
}
},
"pc": {
"configs": [
{
"engine": [
{
"name": "Trident",
"start": "19",
"end": "xxx"
}
],
"channels": [
"zuzuCheJenkinsBuild"
]
}
]
}
}
}
}
}
字段详情
变量名称 类型 备注 eg switchId string 开关id 201810130001 switchCode string 开关编码 TANTU-SW-WEB-DETAIL-0001 switchName string 开关名称 DetailPageSW switchDes string 开关描述 商品详情页新旧版页面切换开关 switchState int 当前开关状态(0:关、1:开) 1 switchDefState int 开关默认状态(0:关、1:开) 0 whitelist Array 白名单列表(pc端为服务代码,m端为muid) {xxx} platforms Object 开关起作用的平台端(mobile,pc) {"mobile":{...}, "pc":{...}} platforms.mobile[sysType] Object m端的系统类型(iOS, Android) {"iOS" : {...}} platforms.mobile[sysType][app] m端的app类型(zzc,tantutravel,tantumap,wechat,aliplay,browser) {"zzc" : {...}} platforms.mobile[sysType][app].configs Array m端开关生效配置 [] ...configs[0].channels Array 渠道来源 ["xxx", "xxx"] ...configs[0].deviceType Array 指定设备类型屏幕 ["all"] ...configs[0].sysVersions Array 设备系统版本范围
Android取值:19(Android4.0), 20(Android5.0), 21(android 5.1), 22(android 5.1.x), 23(android 6.0), 24(android 7.0), 25(android 7.1), 26(android 8.0)...
iOS取值: 8、9、10、11...
[{"start" : "8", "end" : "11"}] ...configs[0].sysVersions.start String 最小值 8 ...configs[0].sysVersions.end String 最大值,xxx表示无限大 xxx ...configs[0].appVersions Array app版本范围,格式跟sysVersions一致 [{"start" : "5.2.1", "end" : "5.2.29"}] platforms.pc.configs Array pc端开关生效配置 [{},{}] platforms.pc.configs[0].engine Array 浏览器的内核配置 [{ "name": "Trident", "start": "19", "end": "xxx" }] platforms.pc.configs[0].engine[0].name String 浏览器的内核名字(Trident,Gecko,Presto,Webkit,Blink) "name": "Trident" platforms.pc.configs[0].engine[0].start String 浏览器的内核版本最小值 8 .platforms.pc.configs[0].engine[0].end String 浏览器的内核版本最大值,xxx表示无限大 xxx