嗨~ 歡迎閱讀 #45 期全端雙週報。在這一期的主題文中,我們會討論現代軟體開發常見的功能旗標。同時本期一樣收錄了許多關於 AI、前後端開發的推薦閱讀。
以上,讓我們進到這期的主題文吧。
什麼是功能旗標 (feature flags)? 為什麼要用功能旗標?
AWS 的 S3 是全世界最多人使用的網路服務之一,而也正是因為非常多服務依賴 S3,在 2017 年 S3 發生的一次重大事故,讓全世界許多網站無法被使用,造成 AWS 損失超過 1.5 億美元。
你可能會想,是什麼重大技術困難,導致如此高額損失的事故?
事實上,該次重大事故的原因是打錯字 (typo)。你沒有看錯,該事故不是什麼重大技術難題導致的,而是因為多數人認為應該要能避免的錯字問題造成的。
雖然很多人可能會把打錯字當成低級錯誤,但事實上打錯字、差一個空格、差一行等看似簡單的問題,假如當到了一個完全不熟悉,且有複雜歷史程式碼的程式碼庫中,即使是很細心的人,也可能會出錯。
因此,從工程的角度來看,該思考的是如何讓相同的錯誤「不可能」再發生。只要有足夠完善的機制,很多人為的錯誤將變得不可能。對此,如果想要成為資深工程師,從這個視角出發思考是很重要的。
在 S3 當年的事故檢討中,針對這個打錯字的問題,總結了幾個最關鍵且能夠透過工程手段避免的點,分別如下:
輸入框沒有做校驗 (input not validated)
配置的更動一次全量推送 (config change pushed out everywhere at once)
回滾沒有自動化 (rollback not automatic)
試想,假如今天輸入框有校驗,這樣打錯字就能夠在配置階段就被發現。再退一步,假如配置不是一次全部推送,而是逐步推送給終端使用者,這樣可以在一開始只推送給小量使用者時就發現,能避免一次推送給全世界,導致一出問題影響範圍就遍及全世界。最後,如果出事故時能有自動偵測並回滾,那將能夠讓問題影響立即止損。
這一期的主題文,我們將會專注在上述三個解決方案中的第二個,來討論如何做到讓更動可以避免一次全部推送。而如同這期主題文標題,具體要實現這個方案的常見做法,會是透過功能旗標 (feature flags)。
所以,什麼是功能旗標 (feature flags)? 為什麼要用它?
所謂的功能旗標,是現代軟體經常會使用的技術,該技術做的事情很簡單,透過某個旗標 (flag),讓軟體在不需用重新部署的狀況下,能夠切換開啟或關閉某個功能。在業界有另一個詞叫功能切換 (feature toggle) 也是指同樣的概念,但由於近年來相關的技術,已經發展到不只是切換開與關,所以目前更多人會用功能旗標這個詞。
這樣講起來很抽象,讓我們透過一個具體的例子來了解。假如今天你在開發一個餐廳論壇的應用程式,想要在該應用程式中,加上一個 AI 聊天機器人,讓造訪的使用者,可以直接問 AI 機器人問題,例如可以問「請告訴我大阪最熱門的 10 間大阪燒店」。
但在上線這個聊天機器人前,假如不想要一次讓所有使用者使用 (因為擔心 AI 的幻覺問題,想要先小部分使用者測試),這時可以透過功能旗標,僅對部分的使用者開啟該 AI 聊天機器人的功能,以下我們以圖示的方式解說。
首先,從程式碼的角度,功能旗標的概念就像下面這段程式碼,透過一個布林的判斷,來決定是否展示某個功能。特別注意,這邊的 user.shouldSee("aiChatbot")
的值,不會是寫死在程式碼庫,而會是寫在某個設定檔 (config file),然後透過功能旗標的管理平台 (例如 LaunchDarkly、PostHog 這種平台,或是 AWS 的 AppConfig) 來管理,所以不需用動程式碼,也可以透過平台去改變 user.shouldSee("aiChatbot")
的值。
if (user.shouldSee("aiChatbot")) {
showAIChatbot();
} else {
showOldFeature();
}
當功能旗標的設定檔中把 AI 聊天功能關上,使用者進到網站就看不到 AI 聊天功能
+------------------------------------+
| 雲端 |
| |
| +------------------------+ |
| | 功能旗標服務 | |
| | +------------------+ | |
| | | 設定檔 | | |
| | | AI 聊天功能:關 | | |
| | +------------------+ | |
| +------------------------+ |
| ^ | |
| | v |
| 2. 確認功能設定 3. 回應設定結果 |
+------------------------------------+
^ |
| v
使用者進入網頁 AI 聊天功能未顯示
然而,可以針對部分使用者,把設定檔中的 AI 聊天功能開啟,這樣這些使用者就能看到
+------------------------------------+
| 雲端 |
| |
| +------------------------+ |
| | 功能旗標服務 | |
| | +------------------+ | |
| | | 設定檔 | | |
| | | AI 聊天功能:開 | | |
| | +------------------+ | |
| +------------------------+ |
| ^ | |
| | v |
| 2. 確認功能設定 3. 回應設定結果 |
+------------------------------------+
^ |
| v
使用者進入網頁 AI 聊天功能顯示
從上面談到的,可以看到,在有了功能旗標後 AWS 當初的事故,將可能被避免,因為在上線階段,可以透過功能旗標先把功能對大部分的使用者隱藏,然後逐步擴量,過程中有遇到問題,則可以隨時關閉該功能。
事實上,這樣的做法,在業界普遍會用金絲雀 (canary) 這個名詞來描述。對於金絲雀部署,或是功能旗標能做到的其他事,例如近年來業界越來越多人在做的「在生產環境上測試(testing on production)」、主幹導向的開發 (Trunk-based Development)、透過功能旗標的分群部署做到 A/B 測試,我們在 E+ 成長計畫都有更多的討論。
想閱讀更多的讀者,歡迎加入 E+ 成長計畫 (點此了解 E+ 的詳細介紹)。
本期推薦
上週社群中有名工程師分享了一個融入了思維鏈 (Chain-of-Thought) 的預提示詞 (pre-prompt),在 GitHub 上獲得千個星星。我們實際試過後,覺得效果非常好 (連結)
過去一週社群討論度很高的 AI 代理套件Browser Use ,透過幾行程式碼就讓 AI 代理與瀏覽器串接在一起,非常厲害 (連結)
談到開發生成式 AI 產品,相信多數人前幾個會想到的名詞中,多半會有提示詞工程 (prompt engineering)。所謂的提示詞 (prompt) 如其名。不過為什麼提示詞也能被稱為「工程」呢? 《提示詞工程 (Prompt Engineering) 基礎》有相關說明 (連結)
函式程式設計 (functional programming) 是近年來在前後端界相當流行的程式撰寫方式。舉例來說,社群最熱門的前端套件 React 就大量使用了函式程式設計的概念。如果對函式程式設計還不熟,可以一讀《函式程式設計 (functional programming) — 宣告式 (declarative)》一文 (連結)
並行 (concurrency) 是許多程式語言讓執行程式時更有效率的方式之一,《How Concurrency Works: A Visual Guide》講解得很清楚 (連結)
在做即時系統時,長輪詢(long polling) 與 WebSockets 經常是會被考慮的方案。在現代前後端開發的脈絡下,WebSockets 是多數團隊的選擇,但在《Back to Basics: Why We Chose Long Polling Over WebSockets》談到並非所有場景都是如此 (連結)
LangGraph 團隊了一個開源 AI 代理的專案,對這主題感興趣的人,推薦可以玩玩 (連結)
多年前 Airbnb 遷出 React Native 後,社群曾有一段時間認為 React Native 未來沒有希望。但是過去幾年 RN 的蓬勃發展,現在 Meta 除外的各大公司,例如 Microsoft、Amazon、Tesla 以及 Shopify 等都大量使用 RN。Shopify 這篇《Five years of React Native at Shopify》 總結了他們的經驗以及使用 RN 的優勢 (連結)