聊一聊基于Nacos的metadata完成服务间的AB测试
背景
在很多時候,產品同學或其他 boss 會有一些想法,或好或壞,都會想放到線上環境去驗證,看看能不能帶來更好的效果。
這其實就是一個提出假設和驗證假設的過程,而 AB 測試,是驗證假設的好方法。
對于服務之間的調用,這一塊其實也是相當符合的。
舉幾個例子吧
A -> B,B 進行了重構
A -> B,B 進行了算法模型的調整
A -> B,B 加入了新特性
...
對于這幾個例子,正常的邏輯都是會讓小部分用戶或流量流進新的 B,觀察一段時間的數據,是否達到預期,再決策 B 是否真的可以上線。
在引入注冊中心 Nacos 之后我們對服務之間調用這一塊可以怎么做到呢?
答案就是 metadata(元數據)!!!
每個應用的實例基本信息比較少,但是 metadata 是可以很豐富的。
我們在向 Nacos Server 進行服務注冊的時候往往會附加一些 metadata ,可以參考官方文檔中 Dubbo 融合 Nacos 成為注冊中心 章節。
對于上述的被調用方新版 B 而已,完全可以把相關內容放進 metadata 中,好比說版本號,特性名等等。
調用方 A 就可以根據當前的用戶來判斷是否要走那個版本的被調用方 B。當然這一步很多公司都會有相應的系統去管理,好比體驗用戶。
也可以看看下面這個流程圖,基本涉及到了。
接下來就根據上面的這個,做一個簡單的例子。
示例
首先是準備兩個被調用方 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"}} }啟動這兩個被調用方,然后可以看到 Nacos 的服務詳情頁大致如下:
后面就是比較關鍵的調用方了。
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"?});//?按照對應的邏輯做對應的地址獲取方式//?這里是: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"); }啟動調用方程序,訪問并指定小于100和大于100的兩個用戶,可以看到調用的雖然是同一個服務,但是一個是訪問的 feature,另一個訪問的是 ?normal。
到這里我們已經可以做到根據不同的邏輯,將用戶導向到相同服務的不同版本上面了。
寫在最后
充分利用好服務實例的 metadata ,可以衍生出許多有意思的實踐。
另外,《Nacos 架構與原理》 的電子書過段時間會放出,大家感興趣的可以關注一下。
nacos-sdk-csharp 的地址 :https://github.com/nacos-group/nacos-sdk-csharp
本文示例代碼的地址 :https://github.com/catcherwong-archive/2021/tree/main/ABTestWithNacos
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的聊一聊基于Nacos的metadata完成服务间的AB测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF 实现圣诞树
- 下一篇: 微软开源的Web测试和自动化神器 Pla