本文来自网易云社区

作者:刘颂

1 项目背景:

2017年5月:客户端提出增加https&dns以及双cdn业务功能 后台配合实现使用disconf配置 针对不同的域名或者请求配置不同的https等信息

2017年7月:考拉上线了工厂店,工厂店产品要求 上线一定时间内 内网灰度 外网不可见 之后某个特定时间 全网开启工厂店  包括首页 搜索 品牌等各个业务模块为了实现这个简单的灰度要求 app 搜索 主站 分别基于disconf实现了多套灰度  一方面代码冗余严重 一方面进行整体操作需要协调多方开发测试进行 徒增风险

2017年8月:随着app 3.8版本开发的开始 多个产品要求针对新增产品进行新老功能的AB实验,如果效果可观会全面开启新功能 基于此,我们觉得有必要将abtest进行统一的设计和服务的提供 在进行技术评审之后 偶然发现有类似功能需求的开发组并不少:

我们希望提供的一个abtest-system需要解决以下问题:

1 产品针对不同场景进行ABTest,从而根据用户行为选择更好的设计方向

2 针对一些上线需要先内测 后公测的功能提供统一的灰度服务

3 对于前端或其他调用方需要进行灰度个性化的支持

2 灰度框架的架构:

1 架构设计上将abtest-system分为了两个工程:

提供后台数据保存以及缓存功能的abtest-generic工程

2 两个工程分工不同 做到功能解耦和

提供前台灰度逻辑计算的abtest-compose工程

3 工作流同样分为两个:

在将数据保存到数据库的同时 abtest-generic新增增量刷新缓存 将缓存保存在solo里

后台通过接入权限控制系统的mobilems-front提供的前台服务 进行结果 条件 资源的增删改查操作

通过kschedule平台每天进行全量的数据同步操作

如果发现调用的缓存数据不存在 那么会调用数据库进行数据同步操作

前台请求过来 通过abtest-compose获取请求信息 调用abtest-generic提供的灰度信息接口进行灰度逻辑运算

进行灰度计算发现出现异常行为 通过哨兵进行报警

3 灰度使用方式和定义:

1 工程间通过dubbo接口调用 是否灰度 对客户端透明

2 灰度工程概念定义  key ---1:n --->  灰度结果  --- 1:n ---> 灰度条件  --- 1:n ---> 灰度配置

2.1 key :调用方定义,定义好后 在灰度工程中配置 不同key应用地方不同 例如https mam 双cdn等 需要不同key

2.3 灰度条件 : 和灰度结果为一对多关系 一个灰度结果可以有多个灰度条件 如果满足其中任意一个灰度条件 即为认定属于灰度访问 返回灰

2.2 灰度结果 : 和key为一对多关系 一个key可以有多个灰度结果 如果满足灰度条件 会将多个灰度结果去重返回的结果

3 使用方式:

3.1 调用方定义key 并且在调用代码中通过对指定key的返回值进行业务逻辑处理

3.2 调用方在灰度后台配置一个或多个灰度配置 用户判断请求数据是否完全满足配置条件

3.3 调用方在灰度后台配置一个或多个灰度条件 用于判断请求是否属于灰度访问 每个灰度条件绑定多个灰度配置

3.4 调用方在灰度后台配置一个或多个同名key的灰度结果 返回调用方需要的数据格式 每个灰度结果绑定多个灰度条件

4 可以创建一些常用的资源配置 例如灰度ip等

6 后台配置关系:

5 灰度结果 资源配置为弹窗形式  灰度条件为页面

4 灰度工程提供出去的方法:

1 根据请求key获取返回结果信息

//key: 调用方定义key

//requestGrayParam:调用方请求灰度工程入参

//返回值body中含有json 需要调用方进一步解析

Response<body> getABTestResult(String key, RequestABTestParam requestABTestParam, ABTestDefaultStrService abTestDefaultStrService);

2 根据请求key返回是否为灰度请求

//key: 调用方定义key

//requestGrayParam:调用方请求灰度工程入参

Boolean isGrayTestIp(String ip) ;

Boolean isABTestRequest(String key, RequestABTestParam requestABTestParam, ABTestDefaultBoolService abTestDefaultBoolService);

3 返回请求ip是否为灰度ip

//ip : 调用方ip

5 工程实现遇到的问题:

5.1 如何保证高并发情况下快速响应:

高并发下的快速响应 主要通过solo缓存方式解决,其中的缓存设计经过三次改版最后形成与后台操作一一对应的方式实现:

1  结果key<--> 结果key内部保存信息 + 结果绑定条件信息

2 条件key<--> 条件key内部保存信息 + 条件绑定资源信息

3 资源key<--> 资源key内部保存信息

通过这三种层次的数据缓存保存 在abtest-compose进行访问的时候入参为结果key 返回值是该结果key所对应的所有条件和条件所对应的所有资源。

在后台进行数据库变更的时候 只需要将相对应的数据同步到缓存即可

在整个缓存的同步和获取的操作中 如果出现异常情况 会进行报警并且手动同步操作

缓存数据流程图:

5.2 如何做到优雅的工程降级:

abtest工程在创建之初就被定义为可降级工程,那么如何做到可以优雅降级呢?

首先 可降级工程代表着工程的降级不会对业务造成不可预料的结果 或者工程的降级 不会导致考拉主业务的阻塞 那么abtest-system的降级就不能对调用方返回统一的默认值 因为不同的调用方对于灰度走A还是走B或者走C都存在不同的业务逻辑处理 如果大促期间的灰度统一返回调用方走A 那么可能对于其中的某些业务对用户的展现并不是产品所期望的。所以对于abtest工程来说 优雅的降级就是abtest不提供任何服务 调用方还可以获取到期望返回值 我这里使用了Dubbo的Stub和SOA系统配合实现该功能 首先 在提供出去的接口中 采用Stub的方式实现提供接口,在后面增加入参的参数为一个默认接口,调用方需要实现该接口进行逻辑操作 可以进行简单计算 也可以直接返回默认值 该接口主要的用于大促降级之后的本地运算 如下图代码:

如代码所示 对正常的业务逻辑进行了try--cache操作,正常情况下可以正常返回abtest灰度计算结果 异常情况下 就会走业务方默认值了

那么问题来了 如何保证abtest系统降级之后 业务方并不是通过访问超时等方式获取异常?

答案就是通过SOA动态配置中的降级配置 强制抛出异常实现,这样当请求走到ZooKeeper的时候 请求不会调用到abtest工程 而是直接返回异常给调用方 调用方捕获异常进行默认值计算和返回  因为我们知道当工程降级之后 希望做的就是没有任何请求打到工程上 才能称得上是真正的降级,那么abtest如何做到这点?

如下图所示:

6 现有不足和后续优化:

现有不足:

1 产品 运营接入成本较高 一方面后台需要配置资源 条件 结果才能生效 一方面没有做成跳转性质的接入方式 后续准备改成在一个页面全部进行配置

2 灰度目前只提供根据udid进行百分比计算 后面需要增加根据accountId 随机以及根据业务方传入值进行随机等

3 灰度结束目前还需要业务方自行配置开关 后面准备增加优雅的灰度结束开关 通过abtest后台系统 一键结束灰度

4 灰度上线后没有明确的数据或者视图表明灰度生效结果,接下来准备深入接入哨兵 提供视图功能可以动态看到灰度效果

整体的二期计划如下图所示:

网易云大礼包:https://www.163yun.com/gift

原文:abtest-system后台系统设计与搭建,经作者刘颂授权发布

相关文章:
【推荐】 接口文档神器Swagger(上篇)

abtest-system后台系统设计与搭建的更多相关文章

  1. redis在Windows下以后台服务一键搭建哨兵(主从复制)模式(多机)

    redis在Windows下以后台服务一键搭建哨兵(主从复制)模式(多机) 一.概述 此教程介绍如何在windows系统中多个服务器之间,布置redis哨兵模式(主从复制),同时要以后台服务的模式运行 ...

  2. redis在Windows下以后台服务一键搭建哨兵(主从复制)模式(单机)

    redis在Windows下以后台服务一键搭建哨兵(主从复制)模式(单机) 一.概述 此教程介绍如何在windows系统中单机布置redis哨兵模式(主从复制),同时要以后台服务的模式运行.布置以脚本 ...

  3. redis在Windows下以后台服务一键搭建集群(多机器)

    redis在Windows下以后台服务一键搭建集群(多机器) 一.概述 此教程介绍如何在windows系统中多台机器之间布置redis集群,同时要以后台服务的模式运行.布置以脚本的形式,一键完成.多台 ...

  4. redis在Windows下以后台服务一键搭建集群(单机--伪集群)

    redis在Windows下以后台服务一键搭建集群(单机--伪集群) 一.概述 此教程介绍如何在windows系统中同一台机器上布置redis伪集群,同时要以后台服务的模式运行.布置以脚本的形式,一键 ...

  5. xutils工具上传日志文件--后台服务器的搭建

    在上一篇文章中使用xutils将手机上保存的日志上传到后台服务器中,现在我们来讲后台服务器是如何搭建的 后台服务器采用jsp+sevlet+mysql的框架 首先讲mysql数据库的表的建立 在fil ...

  6. layui后台框架的搭建

    layui(谐音:类UI) 是一款采用自身模块规范编写的前端 UI 框架,遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用.其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从 ...

  7. 手把手教你使用VUE+SpringMVC+Spring+Mybatis+Maven构建属于你自己的电商系统之vue后台前端框架搭建——猿实战01

            猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是 ...

  8. SpringBoot 整合 Thymeleaf & 如何使用后台模板快速搭建项目

    如果你和我一样,是一名 Java 道路上的编程男孩,其实我不太建议你花时间学 Thymeleaf,当然他的思想还是值得借鉴的.但是他的本质在我看来就是 Jsp 技术的翻版(Jsp 现在用的真的很少很少 ...

  9. 小程序开发之后台SSM环境搭建(一)

    1.新建web项目 打开eclipse,选择file-->New-->Dynamic web Project ,填写项目名字,一直点击next,勾选Generate web.xml dep ...

随机推荐

  1. python:正则模块

    1,正则表达式 正则表达式是用来做字符串的匹配的,正则有他自己的规则,和python没有关系,一种匹配字符串的规则. 2,字符组 在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表 ...

  2. 多目标规划——fgoalattain

    多目标规划 多个目标函数,之间可以用他们的重要程度分析,来一次进行这个序贯算法,当然也可以无限逼近的方案——​ clc,clear; % 约束 a = [- - - - ]; b = [- - ]; ...

  3. serlvet配置xml和@WebServlet

    简单介绍 XML元素不仅是大小写敏感的,而且它们还对出现在其他元素中的次序敏感.例如,XML头必须是文件中的第一项,DOCTYPE声明必须是第二项,而web-app元素必须是第三项.在web-app元 ...

  4. 深入 Struts2 的配置 - 处理多个请求-处理请求结果-模型驱动-异常机制

    转:http://www.java3z.com/cwbwebhome/article/article2/2938.html?id=1631 本部分主要介绍struts.xml的常用配置. 1.1.   ...

  5. AngularJS 三 控制器和事件

    AngularJS控制器: ngularJS中的控制器是一个使用 $ scope 对象维护应用程序数据和行为的JavaScript函数. 您可以将属性和方法附加到控制器函数内的 $ scope  对象 ...

  6. Python 学习笔记(三)数字

    Python 数字 int 整型  是正或负整数  2 long 长整型  整数最后是一个大写或小写的L   2L float  浮点型 由整数部分和小数部分组成   2.0 complex 复数 小 ...

  7. File zilla远程连接服务器报错:服务器发回了不可路由的地址,使用服务器地址代替

    百度的答案都是:更改Filezilla设置,编辑-设置-连接-FTP-被动模式,将“使用服务器的外部ip地址来代替”改为“回到主动模式”即可.但问题没有解决!!! 由于使用的是阿里云的服务器.安全组里 ...

  8. Python基础—15-正则表达式

    正则表达式 应用场景 特定规律字符串的查找替换切割等 邮箱格式.URL.IP等的校验 爬虫项目中,特定内容的提取 使用原则 只要是能够使用字符串函数解决的问题,就不要使用正则 正则的效率较低,还会降低 ...

  9. iOS 获取APP的CPU、内存等信息

    目标是开发一个SDK,嵌入到APP里面,用来统计当前APP的实时CPU.内存等信息 2015.11.17 http://stackoverflow.com/questions/12889422/ios ...

  10. window.location.href url含中文乱码问题

    (1).页面中先对中文进行编码. 如:window.location.href = url+"&groupName=" + encodeURI(encodeURI(grou ...