it

C# Blazor Zero Downtime Deployment — Deploy

C# Blazor Zero Downtime Deployment — Deploy

Blazor Zero Downtime

C# Blazor Zero Downtime Deployment — Deploy

C# Blazor Zero Downtime Deployment Rolling Update Blue-Green Canary SignalR Health Check Graceful Shutdown Kubernetes Production

StrategyDowntimeRollbackResourceComplexity
Rolling UpdateZeroRolling Back+1 Podต่ำ
Blue-GreenZeroInstant (สลับ Traffic)2x Resourceปานกลาง
CanaryZeroส่ง 100% กลับเวอร์ชันเก่า+10-20% Resourceสูง
Recreateมี DowntimeDeploy เวอร์ชันเก่าปกติต่ำ

Rolling Update Configuration

# === Blazor Server Rolling Update === # apiVersion: apps/v1 # kind: Deployment # metadata: # name: blazor-app # spec: # replicas: 3 # strategy: # type: RollingUpdate # rollingUpdate: # maxSurge: 1 # maxUnavailable: 0 # template: # spec: # terminationGracePeriodSeconds: 60 # containers: # - name: blazor # image: registry.example.com/blazor-app:v2.0 # ports: # - containerPort: 8080 # lifecycle: # preStop: # exec: # command: ["/bin/sh", "-c", "sleep 15"] # readinessProbe: # httpGet: # path: /health/ready # port: 8080 # initialDelaySeconds: 5 # periodSeconds: 5 # failureThreshold: 3 # livenessProbe: # httpGet: # path: /health # port: 8080 # initialDelaySeconds: 15 # periodSeconds: 10 # minReadySeconds: 10 # Program.cs - Graceful Shutdown # var builder = WebApplication.CreateBuilder(args); # builder.Services.AddHealthChecks() # .AddDbContextCheck("database") # .AddCheck("signalr", () => HealthCheckResult.Healthy()); # # var app = builder.Build(); # app.MapHealthChecks("/health"); # app.MapHealthChecks("/health/ready"); # # app.Lifetime.ApplicationStopping.Register(() => { # Log.Information("Shutting down gracefully..."); # Thread.Sleep(10000); // Wait for connections to drain # }); from dataclasses import dataclass @dataclass class RollingConfig: setting: str value: str purpose: str blazor_note: str configs = [ RollingConfig("maxSurge", "1", "เพิ่ม Pod ใหม่ 1 ตัวก่อนลบ Pod เก่า", "Pod ใหม่ต้อง Ready ก่อนรับ SignalR Connections"), RollingConfig("maxUnavailable", "0", "ห้ามลด Pod จนกว่า Pod ใหม่ Ready", "ป้องกัน Connection Drop ระหว่าง Deploy"), RollingConfig("minReadySeconds", "10", "รอ 10 วินาทีหลัง Ready ก่อนดำเนินการต่อ", "ให้ SignalR Hub เริ่มต้นเสร็จสมบูรณ์"), RollingConfig("terminationGracePeriodSeconds", "60", "รอ 60 วินาทีก่อน Force Kill", "ให้เวลา SignalR Connection Drain"), RollingConfig("preStop sleep 15", "sleep 15", "รอ 15 วินาทีก่อน SIGTERM", "ให้ Endpoint ถูกถอดจาก Service ก่อน"), ] print("=== Rolling Update Config ===") for c in configs: print(f" [{c.setting}] = {c.value}") print(f" Purpose: {c.purpose}") print(f" Blazor: {c.blazor_note}")

Blue-Green Deployment

# === Blue-Green Deployment Script ===



# # deploy-blue-green.sh

# #!/bin/bash

# NEW_VERSION=$1

# CURRENT=$(kubectl get svc blazor-app -o jsonpath='{.spec.selector.version}')

#

# if [ "$CURRENT" = "blue" ]; then

#   TARGET="green"

# else

#   TARGET="blue"

# fi

#

# # Deploy new version to target

# kubectl set image deployment/blazor-$TARGET \

#   blazor=registry.example.com/blazor-app:$NEW_VERSION

#

# # Wait for rollout

# kubectl rollout status deployment/blazor-$TARGET --timeout=300s

#

# # Run smoke tests

# ENDPOINT=$(kubectl get svc blazor-$TARGET -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# curl -f "http://$ENDPOINT/health/ready" || exit 1

#

# # Switch traffic

# kubectl patch svc blazor-app -p "{\"spec\":{\"selector\":{\"version\":\"$TARGET\"}}}"

#

# echo "Switched to $TARGET (v$NEW_VERSION)"



@dataclass

class BlueGreenStep:

    step: int

    action: str

    command: str

    duration: str

    rollback: str



steps = [

    BlueGreenStep(1, "Deploy to Green",

        "kubectl set image deployment/blazor-green",

        "2-5 นาที",

        "ไม่ต้อง (Blue ยังทำงาน)"),

    BlueGreenStep(2, "Wait for Rollout",

        "kubectl rollout status deployment/blazor-green",

        "1-3 นาที",

        "kubectl rollout undo"),

    BlueGreenStep(3, "Smoke Test Green",

        "curl /health/ready + E2E tests",

        "1-5 นาที",

        "ไม่ Switch ถ้า Test Fail"),

    BlueGreenStep(4, "Switch Traffic",

        "kubectl patch svc (change selector)",

        "< 1 วินาที",

        "Switch กลับ Blue ทันที"),

    BlueGreenStep(5, "Monitor Green",

        "Watch error rate, latency, logs",

        "15-30 นาที",

        "Switch กลับ Blue ถ้าผิดปกติ"),

    BlueGreenStep(6, "Cleanup Blue",

        "Scale down Blue (optional)",

        "ทำเมื่อมั่นใจ",

        "เก็บ Blue ไว้ 24 ชม. ก่อนลบ"),

]



print("=== Blue-Green Steps ===")

for s in steps:

    print(f"  Step {s.step}: {s.action} ({s.duration})")

    print(f"    Command: {s.command}")

    print(f"    Rollback: {s.rollback}")

SignalR Connection Handling

# === SignalR Zero Downtime Handling ===



@dataclass

class SignalRStrategy:

    scenario: str

    problem: str

    solution: str

    config: str



signalr_strategies = [

    SignalRStrategy("Pod Termination",

        "SignalR WebSocket Connection หลุดเมื่อ Pod ถูกลบ",

        "preStop hook + Graceful Shutdown รอ Connection Drain",

        "terminationGracePeriodSeconds: 60, preStop sleep 15"),

    SignalRStrategy("Client Reconnection",

        "Client ต้อง Reconnect หลัง Connection หลุด",

        "Blazor Circuit Reconnect UI + Auto-reconnect",

        "Blazor.start({circuit: {reconnectionOptions}})"),

    SignalRStrategy("Session Affinity",

        "SignalR ต้องกลับ Pod เดิม (Sticky Session)",

        "Ingress Cookie Affinity + Redis Backplane",

        "nginx affinity: cookie + AddSignalR().AddRedis()"),

    SignalRStrategy("State Preservation",

        "Circuit State หายเมื่อ Pod ตาย",

        "เก็บ State ใน Redis/Database ไม่ใช่ Memory",

        "IDistributedCache + Redis State Store"),

    SignalRStrategy("Load Balancer Drain",

        "New Connection ยังถูกส่งมา Pod ที่กำลังจะตาย",

        "Readiness Probe Fail → ถอดจาก Service → Drain",

        "readinessProbe + preStop + SIGTERM handler"),

]



print("=== SignalR Strategies ===")

for s in signalr_strategies:

    print(f"\n  [{s.scenario}]")

    print(f"    Problem: {s.problem}")

    print(f"    Solution: {s.solution}")

    print(f"    Config: {s.config}")

เคล็ดลับ

C# Blazor Zero Downtime Deployment — Deploy
  • preStop: ใช้ preStop sleep 15 ก่อน SIGTERM ให้ Endpoint ถูกถอด
  • Drain: ตั้ง terminationGracePeriodSeconds 60 รอ Connection Drain
  • Redis: ใช้ Redis Backplane สำหรับ SignalR Multi-pod
  • Blue-Green: เก็บ Environment เก่าไว้ 24 ชม. ก่อนลบ
  • Test: รัน Smoke Test ก่อน Switch Traffic ทุกครั้ง

Zero Downtime Deployment คืออะไร

Deploy ไม่หยุดบริการ Rolling Update Blue-Green Canary SignalR Graceful Shutdown Circuit Reconnect Kubernetes ผู้ใช้ไม่รู้สึก

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ PostgreSQL JSONB Learning Path Roadmap

Rolling Update ทำอย่างไร

maxSurge 1 maxUnavailable 0 minReadySeconds 10 terminationGracePeriod 60 preStop sleep Readiness Probe PDB SignalR Drain

แนะนำเพิ่มเติม — อีบุ๊กการลงทุน SiamCafeBook

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง Jaeger Tracing Production Setup Guide

Blue-Green Deployment ทำอย่างไร

2 Environment Blue Green Deploy Green Test Switch Traffic Service Selector Instant Rollback 2x Resource Smoke Test Monitor

Health Check ตั้งอย่างไร

ASP.NET Core AddHealthChecks Liveness /health Readiness /health/ready Startup Probe Database Redis SignalR Graceful Shutdown SIGTERM

แนะนำเพิ่มเติม — iCafeForex

เนื้อหาเกี่ยวข้อง — อ่านต่อ: interest rate แปลว่า

สรุป

C# Blazor Zero Downtime Rolling Update Blue-Green Canary SignalR preStop Graceful Shutdown Health Check Redis Backplane Kubernetes Production

เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: Htmx Alpine.js Monitoring และ Alerting

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง