在產(chǎn)品快速迭代中弦牡,要做到高效的功能發(fā)布同時還要降低上線風(fēng)險(xiǎn),需要采用合適的技術(shù)對功能發(fā)布進(jìn)行精細(xì)化的管控旨涝。FeatureProbe 就是一個高效的功能管理(Feature management)開源服務(wù)租漂,它提供了灰度放量、AB實(shí)驗(yàn)颊糜、實(shí)時配置變更等針對功能粒度的一系列管理能力哩治,本文將介紹如何使用 FeatureProbe 進(jìn)行快速、安全地做功能發(fā)布和迭代衬鱼。
一业筏、動態(tài)配置
如果你沒有接觸過功能管理服務(wù),那相信你對配置中心不會陌生鸟赫。從分布式系統(tǒng)興起之后蒜胖,配置中心已經(jīng)是分布式系統(tǒng)中不可或缺的一部分。從技術(shù)上來說抛蚤,功能管理或配置中心本質(zhì)上都是通過配置規(guī)則動態(tài)控制應(yīng)用程序行為台谢,所帶來的好處是省去了修改代碼、編譯岁经、打包朋沮、部署流程。在動態(tài)配置的實(shí)踐中缀壤,我們通常會以 Key-Value 的形式將配置規(guī)則存儲在某個服務(wù)中統(tǒng)一管理樊拓,并通過數(shù)據(jù)分發(fā)將配置傳輸至應(yīng)用程序中,同時還有一個可以給應(yīng)用程序獲取配置的客戶端庫(SDK)塘慕。
下面通過一個示例演示 Key-Value 配置以及如何通過代碼獲取配置:
// key-value config:
{ "enable_feature_124": true }
// sdk code:
sdkClient.BooleanValue("enable_feature_124") => true
對于一些簡單配置需求都可以用這種 Key-Value 方式組織和獲取配置筋夏,例如:
- “控制功能 #124 關(guān)閉或開啟”
- “將 'name' 文本框的字符大小限制為 256 個字符”
- “redis 的連接地址是 '172.48.1.4:6379' ”
與上述類似的使用方式已經(jīng)在功能開關(guān)、應(yīng)用程序配置图呢、快速限流降級等領(lǐng)域被廣泛應(yīng)用条篷。
上述基于一對一的 Key-Value 映射配置雖然已經(jīng)足夠靈活通用骗随,但仍然難以支持一些較復(fù)雜的功能場景。比如我們很難在 Key-Value 配置中體現(xiàn)如下場景:
- 場景1:“只有從北京訪問的且'級別'是 VIP 的用戶啟用功能 #124”
- 場景2:“只有用戶 APP 版本大于 1.0.1 且在每天 18:00~20:00 時開啟運(yùn)營活動赴叹,否則關(guān)閉活動并顯示‘活動已結(jié)束’的提示信息”
上述場景的特點(diǎn)是應(yīng)用程序在運(yùn)行時需要根據(jù)上下文信息計(jì)算出相應(yīng)的值鸿染,并且當(dāng)上下文(需求)發(fā)生變化時,例如調(diào)整場景一為 “只有北京10%的用戶啟用功能 #124 ” 稚瘾,在不更改代碼的情況下很難做到快速支持牡昆。這也是 FeatureProbe 作為功能管理服務(wù)與傳統(tǒng) Key-Value 配置中心最大的區(qū)別:
配置定義 | SDK | 特點(diǎn) | |
---|---|---|---|
配置中心 | Key-Value | 根據(jù) key 獲取 value | 1、難以在配置中體現(xiàn)業(yè)務(wù)邏輯 2摊欠、難以通過變更配置來快速調(diào)業(yè)務(wù)邏輯 |
功能管理服務(wù) | 由一組表達(dá)業(yè)務(wù)語義的 if / else 邏輯組成 | 根據(jù) key + user 屬性(上下文)來執(zhí)行配置中定義的邏輯并判定出返回的 value | 1丢烘、配置中體現(xiàn)業(yè)務(wù)邏輯 2、變更配置規(guī)則快速調(diào)整業(yè)務(wù)邏輯 |
下面通過一個簡單示例演示功能管理服務(wù)的配置定義以及如何用代碼獲取相應(yīng)的值:
// 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
二些椒、漸進(jìn)式發(fā)布
接下來我們通過一個示例來介紹如何使用 FeatureProbe播瞳,比如當(dāng)我們需要發(fā)布一個新功能時,為了避免新功能的代碼對線上產(chǎn)生影響免糕,我們會使用功能開關(guān) (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
}
當(dāng)我們將新功能代碼部署后,對應(yīng)用程序幾乎不會產(chǎn)生任何影響石窑,因?yàn)樵谀J(rèn)情況下牌芋,所有新功能的代碼都被功能開關(guān)控制,同時是否啟用新功能的開關(guān)初始默認(rèn)值為 false松逊。下面為該功能開關(guān)配置規(guī)則:
FeatuteProbe toggle rules
"enable_feature_123": {
"defaultServe": {
"select": 1 // Return "variations[1]" by default => false
},
"variations": [
true,
false
]
}
當(dāng)我們要對新功能代碼線上驗(yàn)證時躺屁,這時候希望 “城市為 北京,且用戶名為 'test' 或 'admin' 的特定測試用戶才能使用該功能”,以便于這些用戶進(jìn)行功能驗(yàn)證经宏。此時我們會對功能開關(guān)配置進(jìn)行修改犀暑,最終生成的規(guī)則配置如下所示(對應(yīng)規(guī)則執(zhí)行邏輯為右邊注釋):
{
"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
]
}
該配置更新后,會通過我們的數(shù)據(jù)分發(fā)服務(wù) (FeatureProbe Server) 將配置下發(fā)到所有需要使用的應(yīng)用程序中烁兰。當(dāng)應(yīng)用程序每次通過 SDK 獲取返回值時耐亏,它將根據(jù) key + user 屬性以及最新配置規(guī)則所定義的邏輯來計(jì)算相應(yīng)的結(jié)果。
當(dāng)測試用戶 "test" 在 “北京” 測試該新功能發(fā)現(xiàn)問題時沪斟,可以通過將開關(guān)返回值更新回 false 快速關(guān)閉新功能的使用广辰。整個過程不涉及到任何代碼的變更,即便將需求調(diào)整為 “只有北京10%的用戶能訪問該功能”币喧,也僅需在頁面就能完成邏輯的變更操作轨域,然后將新的配置規(guī)則發(fā)布應(yīng)用程序中即可,通常整個過程只需要幾秒鐘杀餐。
當(dāng)功能開關(guān)被開啟后,可以通過數(shù)據(jù)監(jiān)控或集成測試來觀察新功能對應(yīng)用程序造成影響朱巨。當(dāng)驗(yàn)證符合預(yù)期的情況后史翘,可就再進(jìn)一步修改規(guī)則配置來讓更多的用戶使用該功能,如先讓某個城市所有人使用該功能,接著繼續(xù)將用戶擴(kuò)展到多個城市琼讽,并最終擴(kuò)展所有用戶必峰。在整個放量過程中,檢測到任何問題钻蹬,都可以立即更新規(guī)則或關(guān)閉開關(guān)來做到快速回滾吼蚁。通過這種漸進(jìn)式功能發(fā)布 (Progressive Delivery) 的方式,能夠幫助我們實(shí)現(xiàn)快速问欠、安全地進(jìn)行線上變更肝匆。
當(dāng)然,漸進(jìn)式功能發(fā)布只是 FeatureProbe 的使用場景之一顺献,其它基于規(guī)則的配置的場景也都能很好地支持旗国,如按訪問流量放量、基于時間規(guī)則的運(yùn)營活動控制注整、A/B實(shí)驗(yàn)及配置中心等場景能曾。
三、快速試用
目前 FeatureProbe 使用 Apache 2.0 License 協(xié)議已經(jīng)完全開源肿轨。你可以從 GitHub 或 Gitee 上搜索 FeatureProbe 獲取到所有代碼寿冕,為了能夠讓大家快速體驗(yàn)完整的功能服務(wù),我們提供了在線體驗(yàn)環(huán)境椒袍。
四驼唱、總結(jié)
本文主要介紹了如何使用 FeatureProbe 快速更新迭代產(chǎn)品功能,并且通過一個實(shí)際案例介紹如何使用它進(jìn)行漸進(jìn)式的功能發(fā)布槐沼,以降低線上變更的風(fēng)險(xiǎn)曙蒸。在下一篇文章中,我們將介紹 “FeatureProbe的架構(gòu)設(shè)計(jì)和主要特點(diǎn)”岗钩。