本文来自网易云社区

作者:刘颂

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. iOS 代码混淆--pch实现

    之前实现代码的混淆一般是使用sh脚本,不过也是需要把一写需要混淆的方法写到一个文件中(除非是使用特定的命名规范统一混淆), 现在发现,实现代码的混淆pch 文件就可以轻松完成! 1,在新建的工程中 创 ...

  2. c#写入配置文件(text)

    1.获取当前时间 System.DateTime currentTime = new System.DateTime(); currentTime = System.DateTime.Now; 写入配 ...

  3. 三、详述 IntelliJ IDEA 的使用界面

    是否还记得在博文“IntelliJ IDEA 安装目录的核心文件讲解”中,这张充满神秘色彩的图片呢?进入她,让咱们一起感受她的魅力吧! 如上图所示,打开 IntelliJ IDEA 后,首先迎接咱们的 ...

  4. C#实现异步GET的方法

    using System; using System.Collections.Generic; using System.Configuration; using System.IO; using S ...

  5. static函数

    C语言中使用静态函数的好处:      静态函数会被自动分配在一个一直使用的存储区,直到退出应用程序实例,避免了调用函数时压栈出栈,速度快很多.       关键字“static”,译成中文就是“静态 ...

  6. JS中对象继承方式

    JS对象继承方式 摘自<JavaScript的对象继承方式,有几种写法>,作者:peakedness 链接:https://my.oschina.net/u/3970421/blog/28 ...

  7. Django模板简介

    在settings.py中有个TEMPLATES的设置,其中BACKEND用来配置Django模板引擎, DIRS 定义了一个目录列表,模板引擎按列表顺序搜索这些目录以查找模板源文件 一般我们都会把模 ...

  8. 初学Splunk

    splunk简介 https://www.splunk.com/zh-hans_cn/download.html splunk 简体中文版手册 http://docs.splunk.com/Docum ...

  9. ASP.NET安全验证

    一.为什么要用安全验证,使用安全验证有什么好处. 构造特殊的链接地址,导致文件内的数据泄露 数据库泄露 安全防范的首要策略:所有的HTTP访问都要经过IIS,所以限制IIS的安全性是关键 二.安全验证 ...

  10. winform窗体传值和动态添加控件

    1.跳转窗体时传值 //将要显示的页面实例化 RoleMenuForm rmf = new RoleMenuForm(); try { //在此给RoleMenuForm 窗体中的变量roleId传值 ...