前言
本文是團隊內部 ELK(Elasticsearch + Logstash + Kibana)使用分享,涵蓋四大主題:
- Index 架構介紹 — 各索引的用途與對應情境
- Field 介紹 — Elasticsearch Field Type 與 Common Field 說明
- Log Pattern 格式 — 各類型 Log 的解析格式
- Case Study — 實際問題排查流程示範
在 Nuxt 3 中,直接使用 useFetch 或 $fetch 發 API 請求雖然方便,
但在真實專案中你很快會遇到這些問題:
解決方案:將這些橫切關注點(cross-cutting concerns) 集中到一個 composable。
Session 管理是後台系統的核心安全基礎。
一個生產級的 Session 架構需要:
本文拆解一個真實 Nuxt 3 後台系統的完整 Session 架構。
在高並發環境下,當某個 Redis cache key 同時過期,大量請求會同時發現 cache miss 並全部打向後端 DB / Provider,這就是 Cache Stampede。
flowchart TD
E[Cache Key 過期] --> A[Request A Cache Miss]
E --> B[Request B Cache Miss]
E --> C[Request C Cache Miss]
E --> D[Request D Cache Miss]
A --> P[Call Provider]
B --> P
C --> P
D --> P
P --> DB[DB 或 Provider 被打爆]
解決方案: 在更新 Cache 時加 分散式鎖(RedLock),確保同一時間只有一個 instance 去 Provider 取資料並回填 Cache。
一般做法是在每個方法手動埋計時:
1 | // 到處複製貼上,業務邏輯被監控代碼淹沒 |
這違反了 單一職責原則(SRP),監控邏輯和業務邏輯耦合在一起。
典型情境是 多台 App Server 水平擴展,讀取路徑上會先查本機記憶體、再查 共用的 Redis(L2) 當成跨機器的快取來源。業務資料可能在後端更新後寫回 Redis,或依 TTL 在 Redis 上過期;各機的 L1 也會依自己的 TTL 失效。只要出現「同一時間很多請求都認為快取不可用」——例如熱點 key 的 TTL 一起到期、部署後快取清空、或 Redis 短暫不可用後恢復——每一台機、每一條執行緒若都各自回源,後端與 Redis 會在瞬間承受 N 台 × 每機併發 的壓力。
這套 L1(LazyCache)+ L2(Redis) 的組合,目的就是在這種 多機共享快取、又需要週期或事件驅動更新 的架構下,把「miss 之後誰負責載入」收斂成 單機內合併請求,必要時再在 L2 層用分散式鎖(例如 RedLock,見 CacheLayerManager)避免多機同時把同一個 key 打穿到資料庫。它不是取代「資料在業務上如何同步」的設計,而是降低 快取重建瞬間 的並發災難。
正式環境下,前端 JS/CSS 經 Webpack 打包後會帶 content hash 檔名;ASP.NET MVC 的 _Layout.cshtml 必須依 manifest.json 注入正確的 <script> / <link>。本篇說明在 Debug 時如何 不必重啟後端 也能對齊 Webpack 即時編譯 的輸出。
我們的專案 不是「獨立前端站 + 獨立 API 站」那種典型前後端分離:
_Layout.cshtml)在伺服器端渲染,路由與部分畫面由 MVC 負責。vendor.js、index.js 等。_Layout 在 Debug 組態下改把資源 URL 指到 本機 dev server,因此 重新 build / HMR 後只要重新整理頁面,即可載入新 bundle,無須為了更新 hash 而去重啟 IIS 或整個 .NET 站台。簡單講:Release=後端讀記憶體裡的 manifest.json,對應 CDN 上帶 hash 的檔;Debug=後端略過 manifest,改連 dev server 上「當下編譯出來」的固定路徑(無 hash 或 dev 產物),讓「改前端 → 立刻看到畫面」。
當一個請求需要經過多個獨立的檢查/處理步驟,且每個步驟都可以決定「繼續往下傳」或「在這裡中止」,就是責任鏈(Chain of Responsibility)的使用場景。
在後端我們很常把 同一條業務路徑 上的條件拆成 多個彼此獨立的檢查,而不是寫成一大段 if/else 攪在一起。例如提款或資金相關流程可能依序要確認:
每一項都是 不同的業務規則、不同的失敗原因與錯誤訊息。用責任鏈時,一個檢查一個 Handler:職責單一、單元測試好寫、命名也清楚。更重要的是,同一個 Handler 可以在別的流程再組一條鏈——例如「帳號狀態檢查」同時出現在提款、轉帳、兌換;順序與要不要掛某一關,只在組裝鏈的地方決定,不必複製貼上整段邏輯。
下列為 示意(實際類別名與順序依專案而定),重點是 每一關可獨立抽換、也可在別的情境重用:
flowchart TD
W[資金流程請求示意] --> ACC[帳號狀態檢查]
ACC -->|pass| BAL[存款餘額或門檻檢查]
BAL -->|pass| PEND[進行中提款設定檢查]
PEND -->|pass| DONE[後續業務邏輯]
ACC -->|fail| X1[中止並回傳原因]
BAL -->|fail| X2[中止並回傳原因]
PEND -->|fail| X3[中止並回傳原因]
傳統登入只驗證帳號 + 密碼,一旦帳密外洩即全面失守。本需求在既有登入流程中加入第二層驗證(MFA):在使用者完成密碼驗證後、正式取得 Passport 之前,須通過以下其中一種驗證:
| 方法 | 說明 |
|---|---|
| Push Notification | 向已登入的可信裝置推播,由舊手機批准 |
| Email OTP | 發送一次性驗證碼到註冊信箱 |
| TOTP | 使用 Authenticator App(時間型)驗證碼 |
驗證優先級:Push Notification > Email OTP > TOTP(availableMethods[0] 為預設)
flowchart LR
subgraph Legacy["傳統做法 有安全風險"]
L1[Login API] --> L2[驗證帳密]
L2 --> L3[立即回傳 Passport]
L3 --> L4[前端再做 MFA]
end
subgraph CC["CC1-4638 做法"]
C1[Login API] --> C2[驗證帳密]
C2 --> C3["returnCode 0018 不含 Passport"]
C3 --> C4[MFA 驗證通過]
C4 --> C5[產生 Passport]
C5 --> C6[PostLogin]
end
這確保未完成 MFA 的使用者無法取得任何有效 Passport。
在多品牌、多區域、多語系的平台中,首頁的 Banner、Widget、行銷活動區塊都需要能夠由運營人員自行管理,而不是每次改內容都要動到程式碼。市面上有很多成熟的 CMS(WordPress、Strapi 等),但我們的需求比較特殊:
因此我們自建了一套簡易 CMS 系統(代號 CMS),本文完整介紹這套系統的架構設計。