azure 的 App Service 設定, App Configuration, Storage Account (Blob) 比較

這三者雖然都跟「儲存資料」或「設定」有關,但在雲端架構中扮演的角色完全不同。

  • Storage Account 是放「檔案」
  • App Service 設定是放「靜態環境變數」
  • App Configuration 則是放「動態、跨服務的配置中心」


1. 三者的核心差異表

特性App Service (appsettings)Azure App ConfigurationStorage Account (Blob)
主要用途存放單一 Web App 的環境變數。集中管理多個服務的設定。存放非結構化資料(圖片、影片、日誌)。
生效方式修改後 Web App 會重啟支援 熱更新 (Hot Reload),不需重啟。需透過 SDK 讀取檔案內容。
適用規模單一小專案。中大型微服務架構、多環境管理。大量靜態檔案或大數據儲存。
功能重點簡單、直接整合在部署流程。版本控制、標籤 (Label)、功能開關 (Feature Flag)。高擴展性、低成本儲存。

2. 詳細分析

Azure App Service (webapp config appsettings)

這是最基礎的作法。你在 Azure Portal 的「環境變數」中設定的內容,會以環境變數的形式注入到你的程式(如 .NET 的 IConfiguration)。

  • 優點: 設定簡單,與 App Service 綁定,安全性高(可參考 Key Vault)。
  • 缺點: 每次改動設定,Web App 就會重新啟動(Restart),這在正式環境可能會造成短暫的服務中斷。

Azure App Configuration

這是專門為微服務複雜專案設計的配置中心。

  • 集中化: 如果你有 10 個 Web App 都共用同一個資料庫連線字串,你不需要去 10 個地方改,只要在 App Configuration 改一次就好。
  • 功能開關 (Feature Flags): 你可以在不重新部署程式的情況下,在 Portal 上點一下就開啟或關閉某個功能。
  • 標籤管理: 可以針對不同環境(如 Development, Production)使用同一個 Key,但給予不同的標籤值。

Storage Account

這通常不建議用來存放一般的「應用程式設定值」。

  • 用途: 如果你的設定是一個超大的 JSON 檔案或是程式碼需要讀取的配置表(例如:全台門市清單、稅率換算表),且這些資料不會頻繁變動,才會放在這裡。
  • 存取: 程式必須透過 BlobServiceClient 去下載並解析檔案,這比讀取環境變數慢且複雜。

3. 實戰建議:我該選哪一個?

  1. 如果你只有一個 Web App,且設定很少改:直接用 App Service 的環境變數 即可。
  2. 如果你有多個服務(Function, Web App, Container)且需要頻繁切換功能開關:請使用 Azure App Configuration,這能讓你管理起來輕鬆很多。
  3. 如果你的「設定」本身是一個大檔案(如 10MB 的規則庫):請放在 Storage Account,並在 App Configuration 中紀錄該檔案的 URL。

小撇步: 無論用哪一個,如果是敏感資訊(密碼、金鑰),請一律存在 Azure Key Vault,然後在 App Configuration 或 App Service 中引用它。


在 Python (特別是使用 Flask 或 Django 等 Web 框架) 中實作 Azure App Configuration 的動態刷新,核心機制是利用 SDK 提供的 on_refresh_callback 或定期檢查 Sentinel Key (哨兵鍵)

與 .NET 的強型別注入不同,Python 需要手動調用 refresh() 方法來檢查配置是否變動。


1. 核心觀念:Sentinel Key (哨兵鍵)

為了效能,我們不會每次請求都去檢查所有設定。我們會定義一個名為 Sentinel 的 Key,當這個 Key 的值改變時,SDK 才會去拉取所有更新。


2. Python 程式碼實作 (以 Flask 為例)

首先,確保安裝必要的套件:

Bash

pip install azure-appconfiguration-provider flask

範例程式碼:

Python

import os
from flask import Flask
from azure.appconfiguration.provider import load_configuration, SentinelKey

app = Flask(__name__)

# 1. 連線字串 (建議放在環境變數中)
CONNECTION_STRING = os.environ.get("AZURE_APPCONFIG_CONNECTION_STRING")

# 2. 設定哨兵鍵 (當此 Key 變動時,觸發刷新)
select_key = SentinelKey("Sentinel", label="dev")

# 3. 載入配置並設定刷新機制
# refresh_on: 監控的鍵
# refresh_interval: 檢查間隔 (秒),這段時間內呼叫 refresh() 不會真的連網
config = load_configuration(
    connection_string=CONNECTION_STRING,
    refresh_on=[select_key],
    refresh_interval=30 
)

@app.route("/")
def index():
    # 4. 每次請求或定期執行 refresh()
    # SDK 會判斷是否超過 refresh_interval,若超過且 Sentinel 變動,則更新 config
    config.refresh()
    
    # 讀取設定值
    message = config.get("GreetingMessage", "Hello World!")
    return f"<h1>{message}</h1>"

if __name__ == "__main__":
    app.run()

3. 實作細節說明

  • refresh_interval: 這非常重要。如果設為 30 秒,那麼在 30 秒內無論你呼叫幾次 config.refresh(),它都不會去連線 Azure,以節省 API 呼叫成本與效能。
  • 非同步支援: 如果你使用的是 FastAPI,可以使用 load_configuration 的非同步版本(需安裝 azure-appconfiguration-provider 的非同步依賴)。
  • 設定層級:
    • 在 Azure Portal 修改 GreetingMessage 後,必須同時去更新 Sentinel 的值(例如把 1.0 改成 1.1)。
    • SDK 偵測到 Sentinel 變了,才會一次把 GreetingMessage 也同步過來。

4. 為什麼在 Python 中不推薦「全自動」刷新?

在 .NET 中有 Middleware 可以自動處理,但在 Python 中,由於其 WSGI/ASGI 的運行機制,通常建議:

  1. 手動觸發: 在 Web Framework 的 before_request 鉤子中呼叫 refresh()
  2. 背景任務: 使用 threading.Timer 定期在背景執行 refresh(),這樣不會阻塞使用者的請求。

接下來的建議

寫一個背景線程 (Background Thread) 的版本,讓 refresh() 在後台自動執行,而不影響 Web 請求的響應速度

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *