文章目录
- 背景
- Flagsmith 和 Unleash
- 什么是unleash
- 架构
- Unleash Edge
- 安装和使用
- Unleash SDKs
- 开放API Tokens访问
- **`Server-side SDK (CLIENT)`**
- **查询所有 Feature Toggles**
- **查询特定 Toggle**
- API token types
- Client tokens
- Frontend tokens
- Personal access tokens
- Service account tokens
- go sdk demo
背景
功能管理是持续发布/持续部署 ( CI/CD ) 流程的重要组成部分,它允许开发人员与一小部分用户逐步测试新功能、打开或关闭功能以及进行 A/B 测试,以深入了解什么是最有效的,而无需发布一个全新的版本。
对项目内的功能启用进行动态控制, Feature Toggle,
Feature Toggle,顾名思义就是表示 Feature 的开关,通常可以使用 Feature Toggle 来管理不同功能开关,并且可以根据不同的参数对开关进行动态配置。在项目中引入 Feature Toggle 可以更好的对于功能进行灰度发布和定向测试。
Netflix的开源项目Unleash正是这样一款工具,它提供了一种动态管理应用程序功能开关的方式,帮助企业更有效地进行灰度发布、A/B测试和其他迭代策略。
开源方案 Unleash。Unleash 是一个开源的 Feature Toggle 服务。
Flagsmith 和 Unleash
Flagsmith 视频介绍:https://www.reddit.com/r/selfhosted/comments/o5hyug/self_hosted_feature_flag_and_remote_config/?tl=zh-hans
场景 | Flagsmith | Unleash |
---|---|---|
快速集成 | 适合需要 SaaS 或快速启动的项目 | 适合愿意自托管且需要灵活策略的团队 |
复杂策略 | 支持 A/B 测试和用户细分 | 支持更复杂的自定义策略(如渐进式发布) |
边缘计算 | 本地评估减少延迟 | 依赖中心化服务器 |
动态配置 | 支持远程配置参数 | 仅支持功能开关 |
特性 | Flagsmith | Unleash |
---|---|---|
开源版本 | 完全开源(MIT 许可证) | 完全开源(Apache 2.0) |
企业版 | 提供付费 SaaS 和企业支持 | 无官方 SaaS,但有商业支持选项 |
社区支持 | 活跃的社区和文档 | 社区活跃,文档详细 |
- 选择 Flagsmith 如果:
- 需要 SaaS 解决方案或快速启动。
- 需要内置 A/B 测试或动态配置。
- 优先考虑本地评估(如移动端或边缘场景)。
- 选择 Unleash 如果:
- 需要完全自托管和灵活的自定义策略。
- 专注于功能开关和渐进式发布。
- 愿意维护自己的基础设施。
什么是unleash
官方文档:https://docs.getunleash.io/
官方仓库:https://github.com/Unleash
Unleash 是一个开源的功能标志(feature flags) 和管理平台,允许您在不中断服务的情况下安全地发布和测试新功能。它提供了一个集中式界面,用于管理和控制哪些用户可以看到哪些功能,以及如何启用这些功能。
Unleash 提供了一个简单的管理平台,我们可以在这个管理后台上进行 Feature Toggle 的管理和查看。
通过使用Unleash,您的团队可以在不依赖分支的情况下并行开发多个特性,实现敏捷开发的最佳实践。这个平台支持15个官方SDK和多个社区贡献的SDK,可与任何语言和框架无缝集成。
总而言之,Unleash 帮助团队安全地发布和管理新功能,提升了开发效率,并降低了发布风险。
Unleash广泛应用于以下场景:
- 快速迭代:启用或禁用代码以控制新特性的发布速度。
- 灰度发布:逐步向一小部分用户推出新特性,收集反馈并调整。
- A/B测试:对不同用户群体实施不同的功能版本,比较效果。
- 风险控制:若发现新特性有问题,可以通过切换关闭旗标来迅速回滚。
架构
Unleash Edge
官方文档:https://docs.getunleash.io/reference/unleash-edge
https://github.com/Unleash/unleash-edge/blob/main/docs/concepts.md
Unleash Proxy is in maintenance mode. Use Unleash Edge instead.Unleash Proxy 处于维护模式。请改用 Unleash Edge。
Unleash Edge 是 Unleash Proxy 的继任者。如需有关从 Proxy 迁移到 Edge 的帮助,请参阅迁移指南。
Unleash Edge 是 Unleash API 和 SDK 之间快速轻量级的代理层。它充当 Unleash 实例的只读副本,旨在帮助您扩展 Unleash。它允许您支持数千个连接的 SDK,而无需增加对 Unleash 实例发出的请求数量。
- 使用独立于 Unleash 服务器的 Unleash Edge 进行扩展,以支持任意数量的前端客户端,而不会使您的 Unleash 实例过载.
- 前端 SDK 通过 Unleash Edge 连接,以确保隐私、可扩展性和安全性。
Edge 目前支持 2 种不同的模式:
- Edge - 连接到上游节点(Unleash 实例或另一个 Edge)。 支持动态令牌、指标和 其他高级功能;
- 离线 - 没有连接到上游节点。完全控制数据和令牌;
Unleash客户端SDK,可以与Unleash前端API或Unleash代理或Unleash Edge一起使用。这使得任何Flutter应用程序使用Unleash变得非常简单。
主要特性:
- 性能: Edge 使用内存缓存,可以在靠近最终用户的位置运行。单个实例每秒可以处理成千上万个请求。
- 弹性:Edge 旨在在重启后继续运行,即使您与 Unleash 服务器断开连接也能保持功能。
- 安全性: Edge 支持前端应用程序,而不会将敏感数据暴露给最终用户或 Unleash。
您可以在两种不同的模式下运行 Edge:edge 或 offline。要了解有关不同模式和其他 Edge 概念的信息,请访问 Concepts。
安装和使用
参照官方文档 进行安装。
要在本地设置 Unleash,您需要在您的机器上安装 git 和 docker。
执行以下命令:
git clone git@github.com:Unleash/unleash.gitcd unleash
docker compose -f docker-compose-enterprise.yml up -d
这会拉取 unleashorg/unleash-enterprise
Docker 镜像,并使用 Docker Compose 文件来配置 Unleash 服务器及其数据库。
然后将您的浏览器指向 localhost:4242 并使用以下信息登录:
username: admin
password: unleash4all
Unleash SDKs
官方github:https://github.com/Unleash/unleash?tab=readme-ov-file#unleash-sdks
To connect your application to Unleash you’ll need to use a client SDK for your programming language.要将您的应用程序连接到 Unleash,您需要使用适用于您的编程语言的客户端 SDK。
官方服务端 SDK:
- Go SDK
- Java SDK
- Node.js SDK
- PHP SDK
- Python SDK
- Ruby SDK
- Rust SDK
- .NET SDK
官方前端 SDK:
The front-end SDKs connect via Unleash Edge in order to ensure privacy, scalability and security.前端 SDK 通过 Unleash Edge 连接,以确保隐私、可扩展性和安全性。
- Android Proxy SDK
- Flutter Proxy SDK
- iOS Proxy SDK
- JavaScript Proxy SDK
- React Proxy SDK
- Svelte Proxy SDK
- Vue Proxy SDK
开放API Tokens访问
官方文档:https://docs.getunleash.io/reference/api-tokens-and-client-keys
- 后端服务(如 Go) → 选择
Server-side SDK (CLIENT)
Token。 - 前端/移动端 → 选择
Client-side SDK (FRONTEND)
Token。
Server-side SDK (CLIENT)
Token 默认具有 读取权限,可以查询所有 Toggles 的配置。
Client-side SDK (FRONTEND)
Token 可能无法访问某些敏感接口(如 /admin
或 /evaluate
)。
default:production.5050d6c03962ca79170b3360fc8bf0bb3ccc36e1e50ffe5dc88c7257
在 Unleash 中创建 Token 时,选择 Token 类型 取决于你的使用场景。根据你的描述,你正在调试一个 Go 语言后端服务(通过 curl
调用 Unleash API),因此应该选择:
curl
调用的是 Unleash 的 Server API(如/api/client/features
),属于后端调试行为。- 需要读取 Feature Toggles 的完整配置(包括
enabled
状态、variants
、payload
等)。
Server-side SDK (CLIENT)
- 用于 后端服务(如 Go、Node.js、Java 等)连接 Unleash。
- 你的代码中通过
unleash.GetVariant
调用 Unleash,属于 Server-side SDK 的使用方式。
查询所有 Feature Toggles
curl -X GET \-H "Authorization: YOUR_SERVER_SIDE_TOKEN" \"http://unleash.example.com/api/client/features"
查询特定 Toggle
curl -X GET \-H "Authorization: Bearer YOUR_SERVER_SIDE_TOKEN" \"http://unleash.example.com/api/client/features/FEATURE_NAME"
API token types
官方文档:https://docs.getunleash.io/reference/api-tokens-and-client-keys
Client tokens
客户端 token 的作用域限定为一个或多个项目和一个环境。创建客户端 token 时,您可以授予其对特定项目列表或所有当前或未来项目的访问权限。客户端 token 是机密信息,不得向最终用户公开。
Client tokens cannot be used in frontend SDKs; use frontend tokens instead.
客户端 token 不能在前端 SDK 中使用;请改用 前端 token。
Frontend tokens
使用前端 token 将 前端 SDK 通过 Unleash Frontend API 或 Unleash Edge 连接到 Unleash。它们授予用户以下权限:
- Reading enabled flags for a given context针对给定上下文的读取启用标志
- Registering applications with the Unleash server向 Unleash 服务器注册应用程序
- Sending usage metrics
前端令牌的作用域限定为一个或多个项目以及单个环境。创建前端令牌时,您可以授予其对特定项目列表的访问权限,或授予其对所有当前或未来项目的访问权限。前端令牌不被认为是秘密的,可以安全地暴露在客户端。
前端令牌不能在服务器端 SDK 中使用;请改用 客户端令牌。
Personal access tokens
个人访问令牌反映了创建它们的用户所拥有的权限。如果用户的权限发生更改(例如通过添加自定义角色),令牌会自动更新以匹配新的权限。 您可以使用个人访问令牌进行测试、调试或为自动化工具提供临时访问权限。
当您使用个人访问令牌修改资源时,事件会记录该操作的令牌创建者的姓名。
具有生命周期的个人访问令牌会在过期后失效并停止工作。虽然您可以将令牌设置为永不过期,但我们建议使用具有过期日期的令牌,以遵循安全最佳实践。
个人访问令牌不适用于客户端 SDK,因为它们未绑定到环境,可能会过期或其权限可能会更改。请改用 客户端令牌。
Service account tokens
服务帐户令牌为集成和自动化工具提供 API 访问权限。 要了解更多信息,请访问服务帐户。
使用 Edge 将客户端 SDK 连接到 Unleash
To connect a client-side SDK to Unleash using Unleash Edge, you need both a client and frontend token:要想使用 Unleash Edge 将客户端 SDK 连接到 Unleash,你需要一个 客户端 token 和一个 前端 token
- 客户端 SDK 需要一个前端 token 才能与 Edge 通信。
- Edge 需要一个客户端 token 才能与 Unleash 服务器通信。
go sdk demo
package mainimport ("fmt""log""net/http""time""github.com/Unleash/unleash-client-go/v3""github.com/Unleash/unleash-client-go/v3/context"
)func main() {// 初始化 Unleash 客户端err := unleash.Initialize(unleash.WithAppName("my-app"),unleash.WithUrl("http://127.0.0.1:4242/api"),unleash.WithCustomHeaders(http.Header{"Authorization": []string{"x:x.xxx"},}),unleash.WithRefreshInterval(5*time.Second),unleash.WithMetricsInterval(5*time.Second),unleash.WithListener(&unleash.DebugListener{}),)if err != nil {log.Fatalf("初始化失败: %v", err)}// 设置超时等待ready := make(chan struct{})go func() {unleash.WaitForReady()close(ready)}()// 等待就绪或超时select {case <-ready:fmt.Println("Unleash client is ready")case <-time.After(10 * time.Second):log.Fatal("Timeout waiting for Unleash client to be ready")}// 测试用例: 基于参考代码的请求上下文testContext("测试请求", context.Context{UserId: "123",Properties: map[string]string{"UserId": "123"},})// 保持程序运行一段时间以观察结果time.Sleep(15 * time.Second)
}func testContext(name string, ctx context.Context) {isEnabled := unleash.IsEnabled("someToggle", unleash.WithContext(ctx))fmt.Printf("\n=== %s ===\n", name)fmt.Printf("Feature Enabled: %v\n", isEnabled)fmt.Printf("Context:\n")fmt.Printf(" UserId: %s\n", ctx.UserId)fmt.Printf(" Properties:\n")for k, v := range ctx.Properties {fmt.Printf(" %s: %s\n", k, v)}// 获取变体信息variant := unleash.GetVariant("someToggle", unleash.WithVariantContext(ctx))if variant != nil {fmt.Printf("\nVariant Information:\n")fmt.Printf(" Name: %s\n", variant.Name)fmt.Printf(" Enabled: %v\n", variant.Enabled)if variant.Enabled {fmt.Printf(" Payload Type: %s\n", variant.Payload.Type)fmt.Printf(" Payload Value: %s\n", variant.Payload.Value)}} else {fmt.Println("\nNo variant returned")}
}