聊一聊基于Nacos的metadata完成服务间的AB测试
背景
在很多時候,產(chǎn)品同學(xué)或其他 boss 會有一些想法,或好或壞,都會想放到線上環(huán)境去驗證,看看能不能帶來更好的效果。
這其實就是一個提出假設(shè)和驗證假設(shè)的過程,而 AB 測試,是驗證假設(shè)的好方法。
對于服務(wù)之間的調(diào)用,這一塊其實也是相當(dāng)符合的。
舉幾個例子吧
A -> B,B 進行了重構(gòu)
A -> B,B 進行了算法模型的調(diào)整
A -> B,B 加入了新特性
...
對于這幾個例子,正常的邏輯都是會讓小部分用戶或流量流進新的 B,觀察一段時間的數(shù)據(jù),是否達(dá)到預(yù)期,再決策 B 是否真的可以上線。
在引入注冊中心 Nacos 之后我們對服務(wù)之間調(diào)用這一塊可以怎么做到呢?
答案就是 metadata(元數(shù)據(jù))!!!
每個應(yīng)用的實例基本信息比較少,但是 metadata 是可以很豐富的。
我們在向 Nacos Server 進行服務(wù)注冊的時候往往會附加一些 metadata ,可以參考官方文檔中 Dubbo 融合 Nacos 成為注冊中心 章節(jié)。
對于上述的被調(diào)用方新版 B 而已,完全可以把相關(guān)內(nèi)容放進 metadata 中,好比說版本號,特性名等等。
調(diào)用方 A 就可以根據(jù)當(dāng)前的用戶來判斷是否要走那個版本的被調(diào)用方 B。當(dāng)然這一步很多公司都會有相應(yīng)的系統(tǒng)去管理,好比體驗用戶。
也可以看看下面這個流程圖,基本涉及到了。
接下來就根據(jù)上面的這個,做一個簡單的例子。
示例
首先是準(zhǔn)備兩個被調(diào)用方 B。
帶特性的:
var?builder?=?WebApplication.CreateBuilder(args);builder.Services.AddNacosAspNet(builder.Configuration);var?app?=?builder.Build();app.MapGet("/",?()?=> {return?Results.Ok("OK?-?feature"); });app.Run("http://*:9885");{"nacos":?{"ServerAddresses":?[?"http://localhost:8848"?],"DefaultTimeOut":?15000,"Namespace":?"cs","ListenInterval":?1000,"ServiceName":?"providerb","PreferredNetworks":?"192.168","GroupName":?"DEFAULT_GROUP","ClusterName":?"DEFAULT","Weight":?100,"Metadata":?{"version":?"1.0","feature":?"true"}} }正常的:
var?builder?=?WebApplication.CreateBuilder(args);//?Add?services?to?the?container. builder.Services.AddNacosAspNet(builder.Configuration);var?app?=?builder.Build();app.MapGet("/",?()?=> {return?Results.Ok("OK?-?normal"); });app.Run("http://*:9886");{"nacos":?{"ServerAddresses":?[?"http://localhost:8848"?],"DefaultTimeOut":?15000,"Namespace":?"cs","ListenInterval":?1000,"ServiceName":?"providerb","PreferredNetworks":?"192.168","GroupName":?"DEFAULT_GROUP","ClusterName":?"DEFAULT","Weight":?100,"Metadata":?{"version":?"1.0","feature":?"false"}} }啟動這兩個被調(diào)用方,然后可以看到 Nacos 的服務(wù)詳情頁大致如下:
后面就是比較關(guān)鍵的調(diào)用方了。
var?builder?=?WebApplication.CreateBuilder(args);//?Add?services?to?the?container. builder.Services.AddNacosV2Naming(x?=> {x.ServerAddresses?=?new?List<string>?{?"http://localhost:8848/"?};x.Namespace?=?"cs"; });var?app?=?builder.Build();app.MapGet("/req/{id}",?Call);app.Run("http://*:9884");async?Task<IResult>?Call(ILoggerFactory?loggerFactory,?INacosNamingService?svc,?IHttpClientFactory?factory,?int?id) {var?logger?=?loggerFactory.CreateLogger(nameof(Call));var?allIns?=?await?svc.GetAllInstances("providerb",?"DEFAULT_GROUP",?new?List<string>?{?"DEFAULT"?});//?按照對應(yīng)的邏輯做對應(yīng)的地址獲取方式//?這里是:id 小于 100?的走新特性string?address?=?GetAddress(allIns,?id?<?100);var?client?=?factory.CreateClient();var?res?=?await?client.GetStringAsync(address);logger.LogInformation("user={id},url={url},result={res}",?id,?address,?res);return?Results.Ok($"caller?------?{res}"); }string?GetAddress(List<Instance>?instances,?bool?isFeature) {var?str?=?isFeature???"true"?:?"false";var?ins?=?instances.Where(x?=>?x.Healthy?&&?x.Enabled?&&?x.Metadata.TryGetValue("feature",?out?var?feature)?&&?feature.Equals(str)).OrderBy(x=>Guid.NewGuid()).FirstOrDefault();return?ins?!=?null???$"http://{ins.Ip}:{ins.Port}"?:?throw?new?Exception("Can?not?find?out?ins"); }啟動調(diào)用方程序,訪問并指定小于100和大于100的兩個用戶,可以看到調(diào)用的雖然是同一個服務(wù),但是一個是訪問的 feature,另一個訪問的是 ?normal。
到這里我們已經(jīng)可以做到根據(jù)不同的邏輯,將用戶導(dǎo)向到相同服務(wù)的不同版本上面了。
寫在最后
充分利用好服務(wù)實例的 metadata ,可以衍生出許多有意思的實踐。
另外,《Nacos 架構(gòu)與原理》 的電子書過段時間會放出,大家感興趣的可以關(guān)注一下。
nacos-sdk-csharp 的地址 :https://github.com/nacos-group/nacos-sdk-csharp
本文示例代碼的地址 :https://github.com/catcherwong-archive/2021/tree/main/ABTestWithNacos
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的聊一聊基于Nacos的metadata完成服务间的AB测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF 实现圣诞树
- 下一篇: 微软开源的Web测试和自动化神器 Pla