非常好用的開源功能標(biāo)記和遠(yuǎn)程配置服務(wù) - Flagsmith
Flagsmith 是一個(gè)使用 Django 開發(fā)的開源的功能標(biāo)記和遠(yuǎn)程配置服務(wù)??梢圆渴鸬阶约旱乃接性疲蛟诒镜剡\(yùn)行。Flagsmith 可以很輕松地跨 Web、移動(dòng)和服務(wù)器端應(yīng)用創(chuàng)建和管理功能標(biāo)記,只需要用標(biāo)記包裝一段代碼,然后使用 Flagsmith 為不同環(huán)境、用戶打開或關(guān)閉對(duì)應(yīng)的功能即可。
Flagsmith 具有很多特性:
- Feature Flags,通過分階段發(fā)布功能。
- 遠(yuǎn)程配置,輕松打開和關(guān)閉各個(gè)功能,并在不部署新代碼的情況下進(jìn)行更改。
- A/B 和多樣化測(cè)試,可以對(duì)新功能進(jìn)行 A/B 和多元化測(cè)試,還可以引入 beta 程序以獲得早期用戶反饋。
- 組織管理,團(tuán)隊(duì)成員的組織、項(xiàng)目和角色有助于保持部署井井有條。
- 集成,可以使用你最喜歡的工具輕松增強(qiáng) Flagsmith。
Feature Flags 是一種開發(fā)方法,允許你在完成之前發(fā)布代碼和功能。這非常有利于 CI/CD,典型的工作流程如下所示:
- 你即將開始研究一項(xiàng)新功能。讓我們想象你將在應(yīng)用程序中實(shí)現(xiàn)一個(gè)共享按鈕。
- 在 Flagsmith 中創(chuàng)建一個(gè)新功能標(biāo)志,將其命名為 sharing_button。將其設(shè)置為在開發(fā)環(huán)境中啟用,并在生產(chǎn)環(huán)境中禁用。
- 開始開發(fā)該功能。當(dāng)你在 UI 中編寫顯示按鈕的代碼時(shí),將其包裝在條件語句中,針對(duì)標(biāo)志 sharing_button 的值進(jìn)行測(cè)試,僅當(dāng)標(biāo)志設(shè)置為 True 時(shí)才顯示按鈕。
- 因?yàn)槟愕陌粹o僅在 sharing_button 標(biāo)志設(shè)置為 True 時(shí)才會(huì)顯示,所以你可以在使用該功能時(shí)安全地提交代碼,你的代碼將在生產(chǎn)平臺(tái)中運(yùn)行,但功能隱藏在標(biāo)志后面。
- 一旦你覺得功能開發(fā)完成了,你就可以為團(tuán)隊(duì)的其他成員和 Beta 測(cè)試人員啟用 sharing_button 按鈕。
- 如果一切都按預(yù)期工作,只需將生產(chǎn)環(huán)境中的每個(gè)人的 sharing_button 標(biāo)志設(shè)置為 True,那么你的功能就會(huì)出現(xiàn)了。
安裝
可以直接使用 Flagsmith 的官方服務(wù) https://flagsmith.com/。如果要自行托管,則需要執(zhí)行以下步驟來進(jìn)行配置:
- 創(chuàng)建一個(gè) Postgres 數(shù)據(jù)庫來存儲(chǔ) Flagsmith 數(shù)據(jù)。
- 部署 API 服務(wù)并為其設(shè)置 DNS。如果要使用健康檢查,請(qǐng)確保使用 /health 作為健康檢查端點(diǎn)。
- 訪問 http:///api/v1/users/config/init/ 來創(chuàng)建初始超級(jí)管理員并向平臺(tái)提供 DNS 信息。
- 部署前端 Dashboard 并為其設(shè)置 DNS。使用相關(guān)的環(huán)境變量將 Dashboard 指向 API,同樣如果使用健康檢查,請(qǐng)確保使用 /health 作為健康檢查端點(diǎn)。
- 通過 Dashboard 創(chuàng)建一個(gè)新的組織、項(xiàng)目、環(huán)境和標(biāo)志。
- 使用我們的 SDK 時(shí),需要覆蓋它們指向的 API 地址,否則它們將默認(rèn)連接到我們?cè)趆ttps://api.flagsmith.com/api/v1 上的付費(fèi)接口上。
當(dāng)然更推薦的方式是使用 Docker 進(jìn)行一鍵安裝:
git clone git@github.com:flagsmith/self-hosted.git
docker-compose -f self-hosted/docker-compose.yml up
如果你使用 Kubernetes 也可以使用 Helm Chart 來安裝:
helm repo add flagsmith https://flagsmith.github.io/flagsmith-charts/
helm install -n flagsmith --create-namespace flagsmith flagsmith/flagsmith
kubectl -n flagsmith port-forward svc/flagsmith-frontend 8080:8080
然后在瀏覽器中查看 http://localhost:8080,這將使用默認(rèn)選項(xiàng)安裝在新的命名空間 flagsmith 中。上面我們使用 kubectl port-forward 僅僅適用于演示,最好的方式是通過 Ingress 來暴露服務(wù),可以為 flagsmith 設(shè)置以下 values 值,并根據(jù)需要進(jìn)行更改以適應(yīng)你的 Ingress 控制器以及任何相關(guān)的 DNS 更改。
ingress:
frontend:
enabled: true
hosts:
- host: flagsmith.[MYDOMAIN]
paths:
- /
api:
enabled: true
hosts:
- host: flagsmith.[MYDOMAIN]
paths:
- /api/
- /health/
frontend:
extraEnv:
API_URL: 'https://flagsmith.[MYDOMAIN]/api/v1/'
一旦應(yīng)用了任何集群外 DNS 或 CDN 后,就可以在瀏覽器中通過 https://flagsmith.[MYDOMAIN] 訪問服務(wù)了。
由于該應(yīng)用程序是使用 Django 構(gòu)建的,所以我們同樣可以使用 django admin 功能來管理服務(wù)。
概念
Flagsmith 由 2 個(gè)核心組件組成,REST API(位于 /api 中)和基于 Web 的管理員儀表板(位于 /frontend 中),你可以使用它們來管理 Flagsmith。這兩個(gè)組件作為單獨(dú)的應(yīng)用程序運(yùn)行,基于 Web 的儀表板是一個(gè)單頁應(yīng)用程序,它通過 REST 調(diào)用與 API 進(jìn)行通信。
下圖是 Flagsmith 的數(shù)據(jù)模型概述。
組織
組織是你和其他團(tuán)隊(duì)成員管理項(xiàng)目及其功能的一種方式,用戶可以是多個(gè)組織的成員。
項(xiàng)目
項(xiàng)目包含一個(gè)或多個(gè)環(huán)境,這些環(huán)境在項(xiàng)目?jī)?nèi)的所有環(huán)境中共享一組功能。組織可以有任意數(shù)量的項(xiàng)目。
環(huán)境:
環(huán)境是一種分離功能配置的方法。例如,你的項(xiàng)目的開發(fā)和 stage 環(huán)境可能有一個(gè)功能配置為打開,而它在你的生產(chǎn)環(huán)境中被關(guān)閉。一個(gè)項(xiàng)目可以有任意數(shù)量的環(huán)境。
功能
功能在項(xiàng)目中的所有環(huán)境之間共享,但它們的值/狀態(tài)可以在環(huán)境之間進(jìn)行修改。
身份
身份是你項(xiàng)目環(huán)境之一的特定用戶注冊(cè)。在客戶端應(yīng)用程序中注冊(cè)身份允許你管理各個(gè)用戶的功能。身份功能可以從你的環(huán)境默認(rèn)值中覆蓋。例如,joe@yourwebsite.com 在你的開發(fā)環(huán)境中與生產(chǎn)環(huán)境中的身份不同,并且它們可以為每個(gè)環(huán)境啟用不同的功能。
特征
你可以針對(duì)一個(gè)身份存儲(chǔ)任意數(shù)量的特征。特征是簡(jiǎn)單的鍵值對(duì),可以存儲(chǔ)任何類型的數(shù)據(jù)。你可能針對(duì)身份存儲(chǔ)的一些特征示例可能是:
- 用戶登錄的次數(shù)。
- 如果他們已接受申請(qǐng)條款和條件。
- 他們對(duì)應(yīng)用主題的偏好。
- 如果他們?cè)趹?yīng)用程序中執(zhí)行了某些操作。
Segments
Segments 是一種通過特征來定義一組用戶的方式,如登錄次數(shù)、設(shè)備、位置或任何數(shù)量的自定義特征。與單個(gè)用戶類似,你可以覆蓋環(huán)境默認(rèn)的功能。
示例
這里我們以 React 為例進(jìn)行說明如何在項(xiàng)目中集成 Flagsmith,F(xiàn)lagsmith 提供了很多 SDK,這里我們可以直接使用 Flagsmith React SDK。
安裝SDK
通過 NPM 安裝:
npm i flagsmith --save
通過 JavaScript CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/flagsmith/index.js"></script>
基本使用
針對(duì) https://flagsmith.com 上項(xiàng)目中的單個(gè)環(huán)境進(jìn)行初始化,例如開發(fā)或生產(chǎn)環(huán)境。
第 1 步:使用 Flagsmith Provider 包裝你的應(yīng)用
使用 FlagsmithProvider 組件包裝應(yīng)用會(huì)在整個(gè)應(yīng)用程序中提供一個(gè) React 上下文,以便你可以使用 useFlagsmith 和 useFlags hook。
import flagsmith from 'flagsmith'
import {FlagsmithProvider} from 'flagsmith/react'
export function AppRoot() {
<FlagsmithProvider options={{
environmentID: "<YOUR_ENVIRONMENT_KEY>",
}} flagsmith={flagsmith}>
{...}
</FlagsmithProvider>
);
向 Flagsmith provider 傳遞 options 初始化客戶端。
第 2 步:使用 useFlags 訪問特征值和啟用狀態(tài)
包裝在 FlagsmithProvider 中的組件將能夠通過 useFlags 評(píng)估特征值和啟用狀態(tài)以及用戶特征。
import { useFlags } from 'flagsmith/react';
export function MyComponent() {
const flags = useFlags(['font_size'], ['example_trait']); // only causes re-render if specified flag values / traits change
return (
<div className="App">
font_size: {flags.font_size.value}
example_trait: {flags.example_trait}
</div>
);
}
第 3 步:使用 useFlagsmith 訪問 Flagsmith 實(shí)例
包裝在 FlagsmithProvider 中的組件將能夠通過 useFlagsmith 訪問 Flagsmith 的實(shí)例。
import React from 'react';
import { useFlags, useFlagsmith } from 'flagsmith/react';
export function MyComponent() {
const flags = useFlags(['font_size'], ['example_trait']); // only causes re-render if specified flag values / traits change
const flagsmith = useFlagsmith();
const identify = () => {
// This will re-render the component if the user has the trait example_trait or they have a different feature value for font_size
flagsmith.identify('flagsmith_sample_user');
};
const logout = () => {
// This will re-render the component if the user has the trait example_trait or they have a different feature value for font_size
flagsmith.logout();
};
return (
<div className="App">
font_size: {flags.font_size?.value}
example_trait: {flags.example_trait}
{flagsmith.identity ? <button onClick={logout}>Logout</button> : <button onClick={identify}>Identify</button>}
</div>
);
}
這樣就實(shí)現(xiàn)了遠(yuǎn)程控制我們的 React 應(yīng)用。關(guān)于 Flagsmith 的更多使用方法可以參考官方文檔 https://docs.flagsmith.com 了解更多信息。