Blue-Green Deployment — 設計概念
意義角色切流量平行跑兩條線machine steps 說明準備兩套幾乎一樣的正式環境,一套持續服務使用者,另一套靜默部署新版,確認無誤後再把流量切過去
不在使用者正在踩的地板上施工,而是先把隔壁房間裝潢好、確認能住,再把人帶過去
部署流程flowchart TD
A[👤 使用者流量] --> B[🔵 Blue 環境\n舊版持續服務]
C[🟢 Green 環境] --> D[靜默部署新版]
D --> E{健康檢查}
E -->|✅ 通過| F[切流量至 Green]
E -->|❌ 失敗| G[保持 Blue 上線\n放棄本次部署]
F --> H[Blue 降為備援\n隨時可切回]
藍綠 vs 金絲雀兩者常被混淆,但著重點不同:
藍綠佈署
金絲雀佈署
重點
架構(兩套環境)
放量策略
流量方式
一次全切或漸進
先少量真實流量驗證,再逐步擴大
適合情境
需要快速回滾保底
需要低風險漸進驗收
藍綠佈署搭配 weighted target group,同樣可以做到漸進放量,兼顧兩種策略的優點
AL ...
Artifact
Artifact前端 Node.js 生態系的 build 流程Artifact 跟 Docker Image 的關係ASP.NET Core Web API 專案ASP.NET Core Web API 專案Artifact 就是「程式碼經過建置後產生、可以被保存與交付的成品」,讓後面的部署流程不用重新猜你的程式怎麼變成可執行狀態
假設有一個 React 專案
12345678my-app/ src/ App.tsx main.tsx package.json package-lock.json vite.config.ts
轉成某種「可以被執行或部署的結果」Pipeline 會執行
1234567891011121314151617181920212223## 根據 package.json 安裝專案需要的套件, 執行後會產生或更新 node_modules/ package-lock.json## node_modules/ 實際下載回來的套件## package-lock.json 紀錄這次安裝到的精確版本npm install ## OR ...
Helm
Helmhelm 實例Helm 與 KubernetesHelm chartvalues.yamltemplateshelm upgrade --installkubectl apply整條 pipelineSummaryHelm 是 Kubernetes 的「部署打包工具」,它把一堆 Kubernetes YAML 模板,加上環境的設定值,組成真正可以部署的 Kubernetes 資源。也就是,Kubernetes 真正看得懂的是 Deployment、Service、Ingress、ConfigMap 這些 YAML,而 Helm 幫我們產生這些 YAML
Helm 是為了避免每個環境都手刻一大堆 Kubernetes YAML;它讓你用同一套部署模板,搭配不同 values,部署到 QA、Prod、TW、HK 等不同地方。可以把 Helm 想成 template + values = Kubernetes YAML,也就是說 部署模板 + 環境設定 = 真正要丟給 Kubernetes 的部署檔
假設沒有 Helm,要部署一個 API 到 Kubernetes,可能要自己寫很多 ...
NMQ 並發 Race Condition 導致訂單子單轉單遺失分析
事件摘要一筆 HK 市場訂單(TradesOrderGroupId: 2708256)的兩筆子單中,只有一筆成功轉單至 ERP,另一筆(TradesOrderSlaveId: 8877652)轉單失敗,導致 WebStore 的 OrderSlaveFlow 狀態永久卡在 WaitingToTrans,且 ERPDB 中完全沒有該子單的資料。
現象觀察查詢 WebStore 的 OrderSlaveFlow,同一筆訂單的兩筆子單狀態截然不同:
OrderSlaveFlow_Id
TradesOrderSlaveId
StatusDef
TransToERPDateTime
SalesOrderSlaveId
8877547
8877653
WaitingToShipping
2026-05-07 08:16:38
8875983
8877546
8877652
WaitingToTrans
NULL
NULL
8877653 ✅ 正常轉單,有 SalesOrderSlaveId,狀態已推進至 WaitingToShipping
8877652 ❌ 轉單失敗,無任 ...
資料庫存 UTC 嗎
策略 : 資料存 UTC, 顯示才轉時區夏令時間 DST 的陷阱Unix Timestampsummary資料庫存的是「世界上真正發生的那一刻」,畫面顯示才是「這個使用者看到的當地時間」
假設有一個訂單建立時間:2026-05-04 10:00:00,若我們直接存「台灣時間 10:00」,問題是資料庫只看到:2026-05-04 10:00:00,它不知道這是台灣時間、日本時間、紐約時間,還是倫敦時間,因此實際我們會這樣設計
使用者在台灣建立訂單,時間 2026-05-04 10:00:00 GMT+8
轉成 UTC 2026-05-04 02:00:00 UTC
資料庫存 created_at = 2026-05-04T02:00:00Z,其中 Z 代表 UTC
美國使用者查看這筆訂單,假設他在紐約,當地時間是 UTC-4,資料庫拿出 2026-05-04T02:00:00Z
前端轉成紐約時間 2026-05-03 22:00:00
台灣使用者看到 2026-05-04 10:00,而紐約使用者看到 2026-05-03 22:00,兩個人看到的時間不同,但指向的是同一 ...
EF Core 樂觀鎖的假象:BulkExtensions 讓 Rowversion 形同虛設
前言你有沒有遇過這樣的情況:
DB 有 Rowversion 欄位
EF Core Model 設定了 IsRowVersion().IsConcurrencyToken()
但實際測試發現並發更新時,完全沒有任何衝突偵測?
這篇文章從一個真實的促購活動加價購功能出發,完整拆解這個坑是怎麼形成的。
案例背景系統有一張 PromotionEngineSpecialPrice(活動價格表),記錄加價購活動下每個 SKU 的加購價格。
業務流程是:
SCMAPIV2(後台 API)接收營運人員的批次更新請求
驗證通過後,呼叫 PromotionWebAPI 的 POST /api/cart-extra-purchase/batch-update
PromotionWebAPI 查詢現有價格記錄,再批次更新價格與排序
這個流程看起來合理,但有一個隱藏的並發問題。
問題一:Lost Update(更新遺失)情境兩個請求 A、B 同時針對同一個活動的相同 SKU 發起更新:
123456T=0 A 查詢 DB → specialPrice { TypeValue: 100, ...
Autofac - 舊框架注入使用案例
AutofacEFHookReadWrite / ReadOnly一個整合範例summary今天我們的研究專案是是背景 Worker,它不像 Web 專案有 ASP.NET 內建 DI 容器,因此需要自己建立,Autofac 是當時 .NET Framework 生態系中最成熟的選擇
那他怎麼管理?完整生命週期是這樣
123456789101112131415161718程式啟動 ↓BatchUploadProcess.InitContainerBuilder() ↓new ContainerBuilder() ↓builder.RegisterModule(new DAModule()) ← 每個 DB 各一個 ↓builder.RegisterModule(new ServiceModule()) ← BL 層 ↓builder.Build() → IContainer ↓每次 Task 執行時container.BeginLifetimeScope() → ILifetimeScope ↓scope.Resolve<ISales ...
編譯
bin / objcsproj Include版本錯誤案例解析當我們按下「Build」時…
編譯器先把 .cs 程式碼轉成中間結果放在 obj 資料夾,在 obj 裡面會產生有
暫存 DLL
編譯中間檔
自動產生的程式碼(例如 Razor)
當確認所有東西都沒問題後,才會輸出最終結果到 bin 而裡面會有
.dll(主要程式)
.exe(如果是應用程式)
相依套件 DLL(NuGet)
設定檔
也就是說真正執行網站時用的是 bin,而編譯過程中產生一堆暫存在 obj
有時候我們會看到刪掉 bin / obj 的建議來解決版本問題,例如我們若遇到錯誤 ReflectionTypeLoadException,是因為舊的編譯垃圾如果還被拿來用,很可能 bin 裡殘留舊版 DLL、新版 NuGet 已經下載,但舊 DLL 還在、執行時載到錯的版本,而我們刪掉它,就會強制全部重新編譯 + 重新產生正確 DLL
首先,以編譯器本人的角度來說,他不會自己去「找檔案」,它只會編譯「專案明確告訴它要編譯的清單」
當我們啟動 Build,其實是啟動 MSBuild,而 MSBuild ...
INCR / DECR
不就是 +1-1 嗎Basic情境summaryINCR = Increment,也就是增加,別看增加只是數學計算的 +1, +2 的事情,他牽扯的是 “流程” 問題,雖然 Redis 是單執行緒,但因為流程上或程式面,我們通常是把每一個看似簡單的事情,都會拆成一個個 UNIT
1231. GET count2. 程式 +13. SET count newValue
這三步是一個流程,但對 Redis 來說是三條分開的命令,只要是分開的命令,中間就可能插進別人的命令,它雖然一次只做一條,但順序可能變成
1234- A: GET count → 5- B: GET count → 5- A: SET count 6- B: SET count 6
結果就出事了,明明有兩次加一,最後卻只變成 6,不是 7,所以問題根本在「每個 UNIT 的順序是什麼」
sequenceDiagram
participant A as A
participant R as Red
is
participant B as B
Note over A, ...
WAF
WAF 動作模式 count blockCDN / WAF 流量管控策略檢查網路的方式檢查 ipWeb ACLproxy 的 WAFcount 跟 block 是兩種不同的 WAF 動作模式
count 模式意思是規則有命中,會記錄、會統計、會看到 log,但不會真的擋掉請求,用途通常是上線前先觀察規則準不準、看看會不會誤傷正常流量、蒐集資料後再決定要不要正式攔,可以把它理解成先裝監視器,不急著鎖門,因為規則只要看錯一點點,block 擋掉的就可能是自己人,所以很多團隊都會先 count,等確認沒誤殺再下手
block 模式意思是規則有命中,請求會被直接拒絕或攔下,流量進不到後面的服務,用途通常是已經確認這類流量就是不該進來,規則驗證過了,要正式啟用防護可以把它理解成監視器看夠了,現在直接鎖門
如果一開始就 block,風險是
合法來源也被擋掉
第三方串接突然失敗
測試人員以為系統掛了,其實是 WAF 擋掉
排查會變麻煩,因為問題不是程式本身,而是入口規則
所以常見流程會是先掛規則、設成 count、觀察命中來源、修正白名單或條件、再切成 block
情境QA 環境只給公司內部 ...











