ในโลกของ AI application ที่ต้องทำงานตลอด 24 ชั่วโมง การพึ่งพา single AI provider เพียงตัวเดียวนั้นเสี่ยงมาก เคยไหมที่ API ล่มแล้วระบบทั้งระบบหยุดนิ่ง? วันนี้ผมจะสอนวิธี implement Circuit Breaker pattern ที่ผมใช้จริงใน production มาแล้วกว่า 2 ปี ช่วยให้ระบบ graceful fallback ได้อัตโนมัติ

ทำไมต้อง Circuit Breaker Pattern?

ลองนึกภาพว่า AI provider ที่คุณใช้อยู่ล่ม ถ้าไม่มี circuit breaker ระบบจะพยายามเรียก API ที่ล่มไปเรื่อยๆ จน timeout สะสม สร้าง cascade failure ไปถึง downstream services ทำให้ทั้งระบบล่มในที่สุด Circuit Breaker จะทำหน้าที่เป็น "ฟิวส์" ป้องกันไม่ให้ระบบพยายามเรียก service ที่มีปัญหา และ auto-failover ไปใช้ provider สำรองทันที

เปรียบเทียบต้นทุน AI Provider ปี 2026

ก่อนจะเข้าเรื่อง implementation เรามาดูต้นทุนจริงของแต่ละ provider กัน เพราะการ implement failover ที่ดีต้องคำนึงถึง cost-efficiency ด้วย

Providerราคา Output ($/MTok)10M Tokens/เดือน ($)
Claude Sonnet 4.5$15.00$150.00
GPT-4.1$8.00$80.00
Gemini 2.5 Flash$2.50$25.00
DeepSeek V3.2$0.42$4.20

จะเห็นได้ว่า DeepSeek V3.2 มีราคาถูกกว่า Claude Sonnet 4.5 ถึง 35 เท่า ดังนั้นการใช้ Circuit Breaker เพื่อ failover ไป DeepSeek เมื่อ provider หลักล่ม จะช่วยประหยัดค่าใช้จ่ายได้มหาศาล ในขณะที่ยังรักษา uptime ได้สูง

หลักการทำงานของ Circuit Breaker

Circuit Breaker มี 3 states:

Implementation ด้วย Python

นี่คือโค้ดที่ผมใช้ใน production จริง รองรับ multi-provider failover พร้อม Circuit Breaker pattern ที่สมบูรณ์

import time
import asyncio
from enum import Enum
from dataclasses import dataclass, field
from typing import Optional, List, Dict, Any
from collections import defaultdict
import aiohttp
import httpx

class CircuitState(Enum):
    CLOSED = "closed"
    OPEN = "open"
    HALF_OPEN = "half_open"

@dataclass
class CircuitBreakerConfig:
    failure_threshold: int = 5        # จำนวนครั้งที่ล้มเหลวก่อนเปิด circuit
    success_threshold: int = 3        # จำนวนครั้งที่ต้องสำเร็จก่อนปิด circuit
    timeout: float = 30.0            # วินาทีที่จะเปิด circuit ทิ้งไว้
    half_open_timeout: float = 10.0   # วินาทีที่จะลองทดสอบใน half-open state

@dataclass
class CircuitBreaker:
    state: CircuitState = CircuitState.CLOSED
    failure_count: int = 0
    success_count: int = 0
    last_failure_time: float = 0
    config: CircuitBreakerConfig = field(default_factory=CircuitBreakerConfig)
    
    def record_success(self):
        if self.state == CircuitState.HALF_OPEN:
            self.success_count += 1
            if self.success_count >= self.config.success_threshold:
                self.state = CircuitState.CLOSED
                self.failure_count = 0
                self.success_count = 0
        elif self.state == CircuitState.CLOSED:
            self.failure_count = 0
    
    def record_failure(self):
        self.failure_count += 1
        self.last_failure_time = time.time()
        
        if self.state == CircuitState.HALF_OPEN:
            self.state = CircuitState.OPEN
        elif self.failure_count >= self.config.failure_threshold:
            self.state = CircuitState.OPEN
    
    def can_attempt(self) -> bool:
        if self.state == CircuitState.CLOSED:
            return True
        
        if self.state == CircuitState.OPEN:
            elapsed = time.time() - self.last_failure_time
            if elapsed >= self.config.timeout:
                self.state = CircuitState.HALF_OPEN
                self.success_count = 0
                return True
            return False
        
        return True  # HALF_OPEN

class AIProvider:
    def __init__(self, name: str, base_url: str, api_key: str, 
                 model: str, cost_per_mtok: float):
        self.name = name
        self.base_url = base_url
        self.api_key = api_key
        self.model = model
        self.cost_per_mtok = cost_per_mtok
        self.circuit_breaker = CircuitBreaker()
    
    async def call(self, prompt: str, **kwargs) -> Dict[str, Any]:
        if not self.circuit_breaker.can_attempt():
            raise Exception(f"Circuit OPEN for {self.name}")
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": self.model,
            "messages": [{"role": "user", "content": prompt}],
            **kwargs
        }
        
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                f"{self.base_url}/chat/completions",
                headers=headers,
                json=payload
            )
            
            if response.status_code == 200:
                self.circuit_breaker.record_success()
                return response.json()
            else:
                self.circuit_breaker.record_failure()
                raise Exception(f"API Error {response.status_code}: {response.text}")

class AIClientWithFailover:
    def __init__(self):
        self.providers: List[AIProvider] = []
        self.current_index = 0
    
    def add_provider(self, provider: AIProvider):
        self.providers.append(provider)
    
    async def call(self, prompt: str, **kwargs) -> Dict[str, Any]:
        # ลองทุก provider ตามลำดับ
        tried_providers = []
        
        for i in range(len(self.providers)):
            provider = self.providers[(self.current_index + i) % len(self.providers)]
            
            try:
                result = await provider.call(prompt, **kwargs)
                # ถ้าสำเร็จ ย้ายไปใช้ provider นี้ก่อนในครั้งหน้า
                self.current_index = (self.current_index + i) % len(self.providers)
                return result
            except Exception as e:
                tried_providers.append(f"{provider.name}: {str(e)}")
                continue
        
        raise Exception(f"All providers failed: {tried_providers}")

ตัวอย่างการใช้งานกับ HolySheep AI

async def main(): client = AIClientWithFailover() # Provider 1: DeepSeek (ราคาถูก ใช้เป็นหลัก) deepseek = AIProvider( name="DeepSeek-V3.2", base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY", model="deepseek-v3.2", cost_per_mtok=0.42 ) # Provider 2: Gemini (fallback) gemini = AIProvider( name="Gemini-2.5-Flash", base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY", model="gemini-2.5-flash", cost_per_mtok=2.50 ) # Provider 3: GPT-4 (fallback สุดท้าย) gpt4 = AIProvider( name="GPT-4.1", base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY", model="gpt-4.1", cost_per_mtok=8.00 ) client.add_provider(deepseek) client.add_provider(gemini) client.add_provider(gpt4) # เรียกใช้งาน response = await client.call("อธิบายเรื่อง Circuit Breaker Pattern") print(response) if __name__ == "__main__": asyncio.run(main())

Implementation ด้วย TypeScript/Node.js

สำหรับ frontend หรือ Node.js application ผมก็มี implementation ที่ใช้ TypeScript เช่นกัน

enum CircuitState {
  CLOSED = 'CLOSED',
  OPEN = 'OPEN',
  HALF_OPEN = 'HALF_OPEN'
}

interface CircuitBreakerConfig {
  failureThreshold: number;
  successThreshold: number;
  timeout: number;
  halfOpenTimeout: number;
}

interface CircuitBreaker {
  state: CircuitState;
  failureCount: number;
  successCount: number;
  lastFailureTime: number;
}

interface AIProvider {
  name: string;
  baseUrl: string;
  apiKey: string;
  model: string;
  costPerMtok: number;
  circuitBreaker: CircuitBreaker;
}

class AIClientWithFailover {
  private providers: AIProvider[] = [];
  private currentIndex = 0;
  private config: CircuitBreakerConfig = {
    failureThreshold: 5,
    successThreshold: 3,
    timeout: 30000,
    halfOpenTimeout: 10000
  };

  addProvider(provider: Omit): void {
    this.providers.push({
      ...provider,
      circuitBreaker: {
        state: CircuitState.CLOSED,
        failureCount: 0,
        successCount: 0,
        lastFailureTime: 0
      }
    });
  }

  private canAttempt(provider: AIProvider): boolean {
    const cb = provider.circuitBreaker;
    
    if (cb.state === CircuitState.CLOSED) return true;
    
    if (cb.state === CircuitState.OPEN) {
      const elapsed = Date.now() - cb.lastFailureTime;
      if (elapsed >= this.config.timeout) {
        cb.state = CircuitState.HALF_OPEN;
        cb.successCount = 0;
        return true;
      }
      return false;
    }
    
    return true; // HALF_OPEN
  }

  private recordSuccess(provider: AIProvider): void {
    const cb = provider.circuitBreaker;
    
    if (cb.state === CircuitState.HALF_OPEN) {
      cb.successCount++;
      if (cb.successCount >= this.config.successThreshold) {
        cb.state = CircuitState.CLOSED;
        cb.failureCount = 0;
        cb.successCount = 0;
      }
    } else if (cb.state === CircuitState.CLOSED) {
      cb.failureCount = 0;
    }
  }

  private recordFailure(provider: AIProvider): void {
    const cb = provider.circuitBreaker;
    
    cb.failureCount++;
    cb.lastFailureTime = Date.now();
    
    if (cb.state === CircuitState.HALF_OPEN) {
      cb.state = CircuitState.OPEN;
    } else if (cb.failureCount >= this.config.failureThreshold) {
      cb.state = CircuitState.OPEN;
    }
  }

  async call(prompt: string, options?: Record): Promise {
    const triedProviders: string[] = [];

    for (let i = 0; i < this.providers.length; i++) {
      const provider = this.providers[(this.currentIndex + i) % this.providers.length];
      
      if (!this.canAttempt(provider)) {
        triedProviders.push(${provider.name}: circuit OPEN);
        continue;
      }

      try {
        const response = await this.callProvider(provider, prompt, options);
        this.recordSuccess(provider);
        this.currentIndex = (this.currentIndex + i) % this.providers.length;
        return response;
      } catch (error: any) {
        this.recordFailure(provider);
        triedProviders.push(${provider.name}: ${error.message});
        continue;
      }
    }

    throw new Error(All providers failed: ${JSON.stringify(triedProviders)});
  }

  private async callProvider(provider: AIProvider, prompt: string, options?: Record): Promise {
    const response = await fetch(${provider.baseUrl}/chat/completions, {
      method: 'POST',
      headers: {
        'Authorization': Bearer ${provider.apiKey},
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model: provider.model,
        messages: [{ role: 'user', content: prompt }],
        ...options
      })
    });

    if (!response.ok) {
      throw new Error(HTTP ${response.status});
    }

    return response.json();
  }
}

// ตัวอย่างการใช้งาน
async function main() {
  const client = new AIClientWithFailover();

  // DeepSeek (ราคาถูกที่สุด)
  client.addProvider({
    name: 'DeepSeek-V3.2',
    baseUrl: 'https://api.holysheep.ai/v1',
    apiKey: 'YOUR_HOLYSHEEP_API_KEY',
    model: 'deepseek-v3.2',
    costPerMtok: 0.42
  });

  // Gemini (fallback)
  client.addProvider({
    name: 'Gemini-2.5-Flash',
    baseUrl: 'https://api.holysheep.ai/v1',
    apiKey: 'YOUR_HOLYSHEEP_API_KEY',
    model: 'gemini-2.5-flash',
    costPerMtok: 2.50
  });

  // ลองเรียกใช้
  try {
    const result = await client.call('อธิบาย microservices');
    console.log('Success:', result);
  } catch (error) {
    console.error('All providers failed:', error);
  }
}

main();

การ Monitoring และ Metrics

อย่าลืมเพิ่ม monitoring เพื่อติดตามว่า circuit breaker ทำงานบ่อยแค่ไหน

# ตัวอย่าง Prometheus metrics
CIRCUIT_BREAKER_STATE{provider="deepseek"} 0  # 0=closed, 1=open, 2=half-open
CIRCUIT_BREAKER_FAILURES_TOTAL{provider="deepseek"} 127
CIRCUIT_BREAKER_SUCCESSES_TOTAL{provider="deepseek"} 5421
AI_PROVIDER_LATENCY_SECONDS{provider="deepseek",quantile="0.99"} 0.042
AI_PROVIDER_COST_USD{provider="deepseek"} 2.28  # ค่าใช้จ่ายวันนี้

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. Circuit เปิดตลอดเวลาไม่ยอมปิด

สาเหตุ: successThreshold สูงเกินไป หรือ