FeatureProbe:如何快速、安全地进行功能发布

在产品快速迭代中,要做到高效的功能发布同时还要降低上线风险,需要采用合适的技术对功能发布进行精细化的管控。FeatureProbe 就是一个高效的功能管理(Feature management)开源服务,它提供了灰度放量、AB实验、实时配置变更等针对功能粒度的一系列管理能力,本文将介绍如何使用 FeatureProbe 进行快速、安全地做功能发布和迭代。

一、动态配置

如果你没有接触过功能管理服务,那相信你对配置中心不会陌生。从分布式系统兴起之后,配置中心已经是分布式系统中不可或缺的一部分。从技术上来说,功能管理或配置中心本质上都是通过配置规则动态控制应用程序行为,所带来的好处是省去了修改代码、编译、打包、部署流程。在动态配置的实践中,我们通常会以 Key-Value 的形式将配置规则存储在某个服务中统一管理,并通过数据分发将配置传输至应用程序中,同时还有一个可以给应用程序获取配置的客户端库(SDK)。
下面通过一个示例演示 Key-Value 配置以及如何通过代码获取配置:

// key-value config:
{ "enable_feature_124": true }

// sdk code: 
sdkClient.BooleanValue("enable_feature_124") => true

对于一些简单配置需求都可以用这种 Key-Value 方式组织和获取配置,例如:

  • “控制功能 #124 关闭或开启”
  • “将 'name' 文本框的字符大小限制为 256 个字符”
  • “redis 的连接地址是 '172.48.1.4:6379' ”

与上述类似的使用方式已经在功能开关、应用程序配置、快速限流降级等领域被广泛应用。
上述基于一对一的 Key-Value 映射配置虽然已经足够灵活通用,但仍然难以支持一些较复杂的功能场景。比如我们很难在 Key-Value 配置中体现如下场景:

  • 场景1:“只有从北京访问的且'级别'是 VIP 的用户启用功能 #124”
  • 场景2:“只有用户 APP 版本大于 1.0.1 且在每天 18:00~20:00 时开启运营活动,否则关闭活动并显示‘活动已结束’的提示信息”

上述场景的特点是应用程序在运行时需要根据上下文信息计算出相应的值,并且当上下文(需求)发生变化时,例如调整场景一为 “只有北京10%的用户启用功能 #124 ” ,在不更改代码的情况下很难做到快速支持。这也是 FeatureProbe 作为功能管理服务与传统 Key-Value 配置中心最大的区别:

配置定义 SDK 特点
配置中心 Key-Value 根据 key 获取 value 1、难以在配置中体现业务逻辑
2、难以通过变更配置来快速调业务逻辑
功能管理服务 由一组表达业务语义的 if / else 逻辑组成 根据 key + user 属性(上下文)来执行配置中定义的逻辑并判定出返回的 value 1、配置中体现业务逻辑
2、变更配置规则快速调整业务逻辑

下面通过一个简单示例演示功能管理服务的配置定义以及如何用代码获取相应的值:

// feature management config:
"enable_feature_124" : {
  if user ("city" equals "beijing" and "level" equals "vip") : true,
  else                                                       : false
}

// sdk code:
sdkClient.BoolValue("enable_feature_124", {city: "beijing", level: "vip"}) => true
sdkClient.BoolValue("enable_feature_124", {city: "shanghai", level: "vip"}) => false

二、渐进式发布

接下来我们通过一个示例来介绍如何使用 FeatureProbe,比如当我们需要发布一个新功能时,为了避免新功能的代码对线上产生影响,我们会使用功能开关 (Feature toggles) 来控制新功能的代码只能被某个城市的某些用户访问到。代码如下所示:

user := featureprobe.NewUser(reuqest.userid)
                    .With("city", request.city)
                    .With("username": request.username)

enableFeature123 := fpClient.BoolValue("enable_feature_123", user, false)
if enableFeature123 {
  // new code: use the feature
} else {
  // old code: don't use the feature
}

当我们将新功能代码部署后,对应用程序几乎不会产生任何影响,因为在默认情况下,所有新功能的代码都被功能开关控制,同时是否启用新功能的开关初始默认值为 false。下面为该功能开关配置规则:
FeatuteProbe toggle rules

"enable_feature_123": {
      "defaultServe": {
        "select": 1   // Return "variations[1]" by default => false
      },
      "variations": [
        true,
        false
      ]
}

当我们要对新功能代码线上验证时,这时候希望 “城市为 北京,且用户名为 'test' 或 'admin' 的特定测试用户才能使用该功能”,以便于这些用户进行功能验证。此时我们会对功能开关配置进行修改,最终生成的规则配置如下所示(对应规则执行逻辑为右边注释):

{
    "enable_feature_123":{ 
        "rules":[
            {
                "conditions":[ // if city in ["beijing"] 
                    {
                        "type":"string",
                        "subject":"city",
                        "predicate":"is one of",
                        "objects":[
                            "beijing"
                        ]
                    }, // AND
                    {
                        "type":"string", // username in ["test", "admin"]
                        "subject":"username",
                        "predicate":"is one of",
                        "objects":[
                            "test", "admin"
                        ]
                    }
                ]
                "serve":{
                    "select":0 // return "variations[0]"  => true
                },
            }
        ]
         "defaultServe":{ // else
            "select":1 // return "variations[1]"  => false
        }, 
    },
    "variations": [
        true,
        false
      ]
}

该配置更新后,会通过我们的数据分发服务 (FeatureProbe Server) 将配置下发到所有需要使用的应用程序中。当应用程序每次通过 SDK 获取返回值时,它将根据 key + user 属性以及最新配置规则所定义的逻辑来计算相应的结果。

当测试用户 "test" 在 “北京” 测试该新功能发现问题时,可以通过将开关返回值更新回 false 快速关闭新功能的使用。整个过程不涉及到任何代码的变更,即便将需求调整为 “只有北京10%的用户能访问该功能”,也仅需在页面就能完成逻辑的变更操作,然后将新的配置规则发布应用程序中即可,通常整个过程只需要几秒钟。

当功能开关被开启后,可以通过数据监控或集成测试来观察新功能对应用程序造成影响。当验证符合预期的情况后,可就再进一步修改规则配置来让更多的用户使用该功能,如先让某个城市所有人使用该功能,接着继续将用户扩展到多个城市,并最终扩展所有用户。在整个放量过程中,检测到任何问题,都可以立即更新规则或关闭开关来做到快速回滚。通过这种渐进式功能发布 (Progressive Delivery) 的方式,能够帮助我们实现快速、安全地进行线上变更。

当然,渐进式功能发布只是 FeatureProbe 的使用场景之一,其它基于规则的配置的场景也都能很好地支持,如按访问流量放量、基于时间规则的运营活动控制、A/B实验及配置中心等场景。

三、快速试用

目前 FeatureProbe 使用 Apache 2.0 License 协议已经完全开源。你可以从 GitHubGitee 上搜索 FeatureProbe 获取到所有代码,为了能够让大家快速体验完整的功能服务,我们提供了在线体验环境

四、总结

本文主要介绍了如何使用 FeatureProbe 快速更新迭代产品功能,并且通过一个实际案例介绍如何使用它进行渐进式的功能发布,以降低线上变更的风险。在下一篇文章中,我们将介绍 “FeatureProbe的架构设计和主要特点”

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容