it

C# Blazor Pod Scheduling — จัดการ Blazor App บน

C# Blazor Pod Scheduling — จัดการ Blazor App บน

Blazor Pod Scheduling

C# Blazor Pod Scheduling — จัดการ Blazor App บน

C# Blazor Pod Scheduling Kubernetes Docker SignalR WebSocket Sticky Session HPA Health Check .NET 8 Razor Components

AspectBlazor ServerBlazor WASMBlazor United (.NET 8)
RenderServer (SignalR)Browser (WASM)ทั้งสอง (per component)
Sticky Sessionต้องใช้ไม่ต้องขึ้นกับ Component
Image Size80-120MB20-30MB (Nginx)80-120MB
ResourceCPU+RAM มากน้อย (Static)ปานกลาง
Scaleซับซ้อน (Session)ง่าย (Stateless)ปานกลาง
Offlineไม่ได้ได้บางส่วน

Docker Configuration

# === Blazor Docker Setup === # Dockerfile (Blazor Server) # FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build # WORKDIR /src # COPY *.csproj ./ # RUN dotnet restore # COPY . . # RUN dotnet publish -c Release -o /app/publish # # FROM mcr.microsoft.com/dotnet/aspnet:8.0 # WORKDIR /app # COPY --from=build /app/publish . # ENV ASPNETCORE_URLS=http://+:8080 # ENV ASPNETCORE_ENVIRONMENT=Production # EXPOSE 8080 # HEALTHCHECK --interval=30s --timeout=3s \ # CMD curl -f http://localhost:8080/health || exit 1 # ENTRYPOINT ["dotnet", "BlazorApp.dll"] # Program.cs Health Checks # var builder = WebApplication.CreateBuilder(args); # builder.Services.AddHealthChecks() # .AddDbContextCheck("database") # .AddRedis(builder.Configuration["Redis:Connection"], "redis") # .AddUrlGroup(new Uri("https://api.example.com/health"), "external-api"); # # var app = builder.Build(); # app.MapHealthChecks("/health"); # app.MapHealthChecks("/health/ready", new HealthCheckOptions { # Predicate = check => check.Tags.Contains("ready") # }); from dataclasses import dataclass @dataclass class DockerImage: variant: str base_image: str size: str use_case: str images = [ DockerImage("Blazor Server", "mcr.microsoft.com/dotnet/aspnet:8.0", "80-120MB", "Server-side rendering SignalR WebSocket"), DockerImage("Blazor WASM (Nginx)", "nginx:alpine", "20-30MB", "Client-side WASM Static Files"), DockerImage("Blazor United", "mcr.microsoft.com/dotnet/aspnet:8.0", "80-120MB", "Mixed render modes Server + WASM"), DockerImage("SDK (Build Stage)", "mcr.microsoft.com/dotnet/sdk:8.0", "~700MB (build only)", "Compile Publish ไม่อยู่ใน Final"), ] print("=== Docker Images ===") for d in images: print(f" [{d.variant}] {d.base_image}") print(f" Size: {d.size} | Use: {d.use_case}")

Kubernetes Deployment

# === Blazor Server Kubernetes Config ===



# apiVersion: apps/v1

# kind: Deployment

# metadata:

#   name: blazor-server

# spec:

#   replicas: 3

#   template:

#     spec:

#       containers:

#         - name: blazor

#           image: registry.example.com/blazor-app:v1.0

#           ports:

#             - containerPort: 8080

#           env:

#             - name: ConnectionStrings__Default

#               valueFrom:

#                 secretKeyRef:

#                   name: blazor-secrets

#                   key: db-connection

#           resources:

#             requests:

#               cpu: 250m

#               memory: 256Mi

#             limits:

#               cpu: "1"

#               memory: 512Mi

#           livenessProbe:

#             httpGet:

#               path: /health

#               port: 8080

#             initialDelaySeconds: 10

#             periodSeconds: 15

#           readinessProbe:

#             httpGet:

#               path: /health/ready

#               port: 8080

#             initialDelaySeconds: 5

#             periodSeconds: 10

# ---

# # Ingress with Sticky Session (for SignalR)

# apiVersion: networking.k8s.io/v1

# kind: Ingress

# metadata:

#   annotations:

#     nginx.ingress.kubernetes.io/affinity: "cookie"

#     nginx.ingress.kubernetes.io/session-cookie-name: "blazor-affinity"

#     nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"

#     nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"



@dataclass

class K8sConfig:

    resource: str

    key_setting: str

    blazor_server: str

    blazor_wasm: str



configs = [

    K8sConfig("Deployment",

        "replicas",

        "3 (ต้อง Sticky Session)",

        "3 (Stateless Scale ง่าย)"),

    K8sConfig("Ingress",

        "affinity",

        "cookie (SignalR WebSocket)",

        "ไม่ต้อง (Static Files)"),

    K8sConfig("Ingress",

        "proxy-timeout",

        "3600s (WebSocket long-lived)",

        "60s (ปกติ)"),

    K8sConfig("Service",

        "sessionAffinity",

        "ClientIP (Sticky Session)",

        "None (Round Robin)"),

    K8sConfig("HPA",

        "metric",

        "CPU > 70% (Min 2 Max 10)",

        "CPU > 70% (Min 2 Max 20)"),

    K8sConfig("Resources",

        "request/limit",

        "CPU 250m-1 Memory 256Mi-512Mi",

        "CPU 50m-200m Memory 64Mi-128Mi"),

]



print("=== K8s Configuration ===")

for c in configs:

    print(f"  [{c.resource}] {c.key_setting}")

    print(f"    Server: {c.blazor_server}")

    print(f"    WASM: {c.blazor_wasm}")

Scaling & Monitoring

# === Blazor Scaling Strategy ===



@dataclass

class ScaleStrategy:

    scenario: str

    challenge: str

    solution: str

    config: str



scaling = [

    ScaleStrategy("Blazor Server Scale Out",

        "SignalR WebSocket ต้อง Sticky Session ย้าย Pod ไม่ได้",

        "ใช้ Azure SignalR Service หรือ Redis Backplane",

        "AddSignalR().AddRedis(redisConnectionString)"),

    ScaleStrategy("Session Affinity Failover",

        "ถ้า Pod ตาย Session หาย User ต้อง Reconnect",

        "ตั้ง Circuit Reconnect UI แจ้ง User + Auto-reconnect",

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

    ScaleStrategy("WASM CDN Distribution",

        "WASM Files 5-20MB ต้อง Download ครั้งแรก",

        "ใช้ CDN Cache + Brotli Compression + Service Worker",

        "Cache-Control: public, max-age=31536000"),

    ScaleStrategy("Database Connection Pool",

        "Pod เพิ่ม Connection Pool หมด",

        "ใช้ PgBouncer / ProxySQL + Connection Pool Limit",

        "MaxPoolSize=50 per Pod"),

]



@dataclass

class MonitorMetric:

    metric: str

    source: str

    alert: str



monitoring = [

    MonitorMetric("SignalR Connection Count",

        "dotnet_signalr_connections_current",

        "> 1000 connections/pod → Scale out"),

    MonitorMetric("Request Duration p99",

        "http_request_duration_seconds",

        "> 500ms → Check DB/External API"),

    MonitorMetric("Memory Usage",

        "container_memory_usage_bytes",

        "> 80% limit → Scale up/out"),

    MonitorMetric("Health Check Status",

        "/health endpoint",

        "Unhealthy → Alert + Auto-restart"),

    MonitorMetric("WebSocket Errors",

        "signalr_errors_total",

        "> 1% error rate → Check Network"),

]



print("=== Scaling ===")

for s in scaling:

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

    print(f"    Challenge: {s.challenge}")

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



print("\n=== Monitoring ===")

for m in monitoring:

    print(f"  [{m.metric}] {m.source}")

    print(f"    Alert: {m.alert}")

เคล็ดลับ

C# Blazor Pod Scheduling — จัดการ Blazor App บน
  • SignalR: ใช้ Redis Backplane สำหรับ Blazor Server Multi-pod
  • Sticky: ตั้ง Cookie Affinity สำหรับ Ingress WebSocket
  • WASM: ใช้ Brotli Compression ลด WASM Download Size 60%
  • Health: ตั้ง Health Check ตรวจ DB Redis External API
  • .NET 8: ใช้ Blazor United เลือก Render Mode ต่อ Component

Blazor คืออะไร

Web Framework C# Microsoft Razor Components Server SignalR WASM WebAssembly United .NET 8 NuGet Entity Framework Interactive UI

เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: CircleCI Orbs Low Code No Code

อ่านเพิ่ม: Container Orchestration นอกจาก Kubernetes มีอะไรอีก? Docker · อ่านเพิ่ม: Kubernetes ขั้นสูง สอน Helm Charts, Operators, Service Mesh · อ่านเพิ่ม: Kubernetes Operators และ CRD คืออะไร? สอนสร้าง Custom Contro

Docker ตั้งค่าอย่างไร

Multi-stage dotnet/sdk dotnet/aspnet nginx:alpine dotnet publish Release Health Check ENTRYPOINT 80-120MB Docker Compose SQL Server Redis

แนะนำเพิ่มเติม — ติดตาม XM Signal

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง AWS EventBridge DNS Management

Kubernetes Deploy อย่างไร

Deployment Replicas Ingress Cookie Affinity SignalR WebSocket Timeout HPA Service sessionAffinity ConfigMap Secret Liveness Readiness Probe

เนื้อหาเกี่ยวข้อง — Azure Container Apps API Gateway Pattern

Health Check ทำอย่างไร

ASP.NET Core AddHealthChecks DbContext Redis URL Disk MapHealthChecks /health /health/ready Liveness Readiness Startup Probe UI Dashboard

แนะนำเพิ่มเติม — อ่านเพิ่มเติมที่ SiamCafeBook

สรุป

C# Blazor Pod Scheduling Kubernetes Docker SignalR Sticky Session HPA Health Check .NET 8 WASM Redis Backplane Ingress Production

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ Lit Element Remote Work Setup

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

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