สรุปคำตอบภายใน 30 วินาที

บทความนี้สอนวิธีตั้งค่า Rate Limiting, Retry Logic, SLA Monitoring และ Failover สำหรับ HolySheep Agent เพื่อให้ระบบ Production ทำงานเสถียร ประหยัดค่าใช้จ่าย และรองรับ Traffic สูงได้โดยไม่ต้องกังวลเรื่อง API ล่ม สิ่งที่คุณจะได้:

บทนำ: ทำไมต้องตั้งค่า Rate Limiting และ Failover?

จากประสบการณ์การพัฒนาระบบ AI ขนาดใหญ่ ปัญหาที่พบบ่อยที่สุดคือ:

ด้วย HolySheep AI คุณได้รับความหน่วงต่ำกว่า 50ms พร้อมอัตราประหยัดมากกว่า 85% เมื่อเทียบกับ API ทางการ แต่ถ้าตั้งค่าไม่ดี ก็อาจเสียโอกาสและเสียเงินได้เช่นกัน

โครงสร้างหลักของระบบ

ก่อนเข้าสู่โค้ด มาดูโครงสร้างระบบที่เราจะสร้างกัน:

┌─────────────────────────────────────────────────────────────┐
│                      Client Application                       │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│                   HolySheep Agent SDK                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐   │
│  │Rate Limiter │→│   Retry     │→│   Failover Switch    │   │
│  │   (Token    │  │  (Exp.     │  │   (Auto-switch      │   │
│  │   Bucket)   │  │  Backoff)  │  │    when down)       │   │
│  └─────────────┘  └─────────────┘  └─────────────────────┘   │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│                   SLA Monitor                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐   │
│  │   Latency   │  │   Error     │  │   Uptime            │   │
│  │   Tracker   │  │   Rate      │  │   Checker           │   │
│  └─────────────┘  └─────────────┘  └─────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

การตั้งค่า Rate Limiter อัจฉริยะ

Rate Limiter เป็นหัวใจสำคัญของการประหยัดค่าใช้จ่าย ถ้าตั้งค่าถูกต้อง คุณจะไม่ถูก Block และใช้งานได้อย่างมีประสิทธิภาพสูงสุด

// holy_sheep_agent.js - Rate Limiter with Token Bucket Algorithm
const HolySheepAgent = require('./holy_sheep_sdk');

class RateLimiter {
  constructor(options = {}) {
    // ตั้งค่า Token Bucket
    this.tokens = options.maxTokens || 100;  // จำนวน Token สูงสุด
    this.maxTokens = options.maxTokens || 100;
    this.refillRate = options.refillRate || 10;  // Token ที่เติมต่อวินาที
    this.lastRefill = Date.now();
    
    // ตั้งค่า HolySheep Client
    this.client = new HolySheepAgent({
      apiKey: process.env.HOLYSHEEP_API_KEY,
      baseURL: 'https://api.holysheep.ai/v1',  // URL หลักเท่านั้น
      timeout: 30000,
      maxRetries: 3
    });
    
    // ตั้งค่า Tier-based Limits
    this.tierLimits = {
      'gpt-4.1': { rpm: 50, tpm: 50000, rpd: 100000 },
      'claude-sonnet-4.5': { rpm: 40, tpm: 40000, rpd: 80000 },
      'gemini-2.5-flash': { rpm: 100, tpm: 100000, rpd: 200000 },
      'deepseek-v3.2': { rpm: 200, tpm: 200000, rpd: 500000 }
    };
  }

  // ฟังก์ชันเติม Token อัตโนมัติ
  async refillTokens() {
    const now = Date.now();
    const secondsPassed = (now - this.lastRefill) / 1000;
    const tokensToAdd = secondsPassed * this.refillRate;
    
    this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);
    this.lastRefill = now;
  }

  // รอ Token ว่าง
  async waitForToken() {
    await this.refillTokens();
    
    if (this.tokens < 1) {
      const waitTime = (1 - this.tokens) / this.refillRate * 1000;
      await new Promise(resolve => setTimeout(resolve, waitTime));
      await this.refillTokens();
    }
    
    this.tokens -= 1;
  }

  // ตรวจสอบ Tier Limits
  checkTierLimits(model, requests, tokens) {
    const limits = this.tierLimits[model];
    if (!limits) return true;
    
    return requests <= limits.rpm && tokens <= limits.tpm;
  }

  // ส่ง Request พร้อม Rate Limiting
  async chat(model, messages, options = {}) {
    await this.waitForToken();  // รอจนกว่าจะมี Token ว่าง
    
    const startTime = Date.now();
    
    try {
      const response = await this.client.chat.completions.create({
        model: model,
        messages: messages,
        temperature: options.temperature || 0.7,
        max_tokens: options.max_tokens || 2048
      });
      
      const latency = Date.now() - startTime;
      console.log(✅ Request สำเร็จ | Model: ${model} | Latency: ${latency}ms);
      
      return {
        success: true,
        data: response,
        latency: latency,
        cost: this.calculateCost(model, response.usage.total_tokens)
      };
      
    } catch (error) {
      throw this.handleError(error, model, messages, options);
    }
  }

  calculateCost(model, tokens) {
    const pricing = {
      'gpt-4.1': { input: 0.002, output: 0.008 },  // $8/MTok output
      'claude-sonnet-4.5': { input: 0.003, output: 0.015 },  // $15/MTok
      'gemini-2.5-flash': { input: 0.0001, output: 0.0005 },  // $2.50/MTok
      'deepseek-v3.2': { input: 0.00007, output: 0.00028 }  // $0.42/MTok
    };
    
    const rates = pricing[model] || pricing['deepseek-v3.2'];
    return (tokens / 1000000) * rates.output;
  }

  handleError(error, model, messages, options) {
    // จัดการ Rate Limit Error
    if (error.status === 429) {
      console.warn('⚠️ Rate Limit Hit — รอ 60 วินาที');
      return { type: 'rate_limit', retryAfter: 60 };
    }
    
    // จัดการ Timeout
    if (error.code === 'ETIMEDOUT') {
      console.warn('⚠️ Timeout — ลองใหม่ด้วย Model ที่เร็วกว่า');
      return { type: 'timeout', suggestModel: 'gemini-2.5-flash' };
    }
    
    return error;
  }
}

module.exports = RateLimiter;

การตั้งค่า Retry กับ Exponential Backoff

Retry ที่ถูกต้องต้องมี Exponential Backoff เพื่อไม่ให้ Server ล่มจาก Traffic พุ่ง ตัวอย่างด้านล่างใช้ Jitter เพื่อกระจาย Request ให้สม่ำเสมอ

// retry_handler.js - Smart Retry with Exponential Backoff & Jitter
class RetryHandler {
  constructor(options = {}) {
    this.maxRetries = options.maxRetries || 5;
    this.baseDelay = options.baseDelay || 1000;  // 1 วินาที
    this.maxDelay = options.maxDelay || 30000;   // 30 วินาที
    this.jitterFactor = options.jitterFactor || 0.3;  // 30% Jitter
    
    // กำหนดว่า Error แบบไหนควร Retry
    this.retryableErrors = new Set([
      408,  // Request Timeout
      429,  // Rate Limit
      500,  // Internal Server Error
      502,  // Bad Gateway
      503,  // Service Unavailable
      504   // Gateway Timeout
    ]);
    
    // กำหนดว่า Error แบบไหนไม่ควร Retry
    this.nonRetryableErrors = new Set([
      400,  // Bad Request
      401,  // Unauthorized
      403,  // Forbidden
      404   // Not Found
    ]);
  }

  // คำนวณ Delay ด้วย Exponential Backoff + Jitter
  calculateDelay(attempt) {
    // Exponential Backoff: 1s, 2s, 4s, 8s, 16s...
    const exponentialDelay = this.baseDelay * Math.pow(2, attempt);
    
    // เพิ่ม Jitter เพื่อกระจาย Request (ป้องกัน Thundering Herd)
    const jitter = exponentialDelay * this.jitterFactor * Math.random();
    
    // ห้ามเกิน Max Delay
    return Math.min(exponentialDelay + jitter, this.maxDelay);
  }

  // ตรวจสอบว่าควร Retry หรือไม่
  shouldRetry(error, attempt) {
    // เกินจำนวนครั้งที่กำหนดแล้ว
    if (attempt >= this.maxRetries) {
      return false;
    }
    
    // ไม่ใช่ HTTP Error
    if (!error.status) {
      return error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET';
    }
    
    // เช็คว่าเป็น Retryable Error หรือไม่
    return this.retryableErrors.has(error.status);
  }

  // ฟังก์ชันหลักสำหรับ Retry
  async executeWithRetry(fn, context = {}) {
    let lastError;
    const retryHistory = [];
    
    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
      try {
        console.log(🔄 Attempt ${attempt + 1}/${this.maxRetries + 1});
        
        const result = await fn();
        
        // บันทึก Retry Success
        if (attempt > 0) {
          retryHistory.push({
            attempt: attempt,
            latency: result.latency || 0,
            success: true
          });
          console.log(✅ Retry สำเร็จที่ Attempt ${attempt + 1});
        }
        
        return result;
        
      } catch (error) {
        lastError = error;
        
        // บันทึก Retry History
        retryHistory.push({
          attempt: attempt,
          error: error.message,
          status: error.status,
          timestamp: new Date().toISOString()
        });
        
        console.error(❌ Attempt ${attempt + 1} ล้มเหลว: ${error.message});
        
        // ถ้าเป็น Non-Retryable Error ให้หยุดทันที
        if (this.nonRetryableErrors.has(error.status)) {
          console.error('🚫 ไม่สามารถ Retry ได้ — Error นี้ไม่รองรับ');
          throw error;
        }
        
        // ถ้าควร Retry ให้รอก่อน
        if (this.shouldRetry(error, attempt)) {
          const delay = this.calculateDelay(attempt);
          console.log(⏳ รอ ${Math.round(delay)}ms ก่อนลองใหม่...);
          await this.sleep(delay);
        } else {
          console.error('🚫 เกินจำนวนครั้งที่กำหนด หยุด Retry');
          throw error;
        }
      }
    }
    
    // ถ้า Retry หมดแล้วยังล้มเหลว
    throw this.wrapError(lastError, retryHistory);
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  wrapError(error, history) {
    return {
      ...error,
      retryHistory: history,
      message: หลังจาก Retry ${this.maxRetries} ครั้งแล้วยังล้มเหลว: ${error.message},
      final: true
    };
  }
}

// ตัวอย่างการใช้งาน
const retryHandler = new RetryHandler({
  maxRetries: 5,
  baseDelay: 1000,
  maxDelay: 30000,
  jitterFactor: 0.3
});

async function callAPI(model, messages) {
  const rateLimiter = new RateLimiter();
  return await retryHandler.executeWithRetry(
    () => rateLimiter.chat(model, messages),
    { model, timestamp: Date.now() }
  );
}

module.exports = RetryHandler;

การตั้งค่า SLA Monitor

SLA Monitor ช่วยให้คุณรู้สถานะของ API แบบ Real-time และส่ง Alert เมื่อมีปัญหา

// sla_monitor.js - Real-time SLA Monitoring with Alerting
class SLAMonitor {
  constructor(options = {}) {
    this.slaTargets = {
      uptime: options.uptime || 99.9,      // เป้าหมาย Uptime 99.9%
      latencyP50: options.latencyP50 || 100,  // Latency P50 < 100ms
      latencyP99: options.latencyP99 || 500,  // Latency P99 < 500ms
      errorRate: options.errorRate || 1       // Error Rate < 1%
    };
    
    this.metrics = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      latencies: [],
      errors: [],
      lastCheck: null,
      consecutiveFailures: 0
    };
    
    this.alertCallbacks = [];
    this.healthCheckInterval = options.healthCheckInterval || 30000; // 30 วินาที
    this.startMonitoring();
  }

  // เริ่มตรวจสอบสุขภาพอัตโนมัติ
  startMonitoring() {
    this.monitorInterval = setInterval(() => {
      this.performHealthCheck();
    }, this.healthCheckInterval);
  }

  // บันทึก Request
  recordRequest(request) {
    this.metrics.totalRequests++;
    this.metrics.lastCheck = Date.now();
    
    if (request.success) {
      this.metrics.successfulRequests++;
      this.metrics.latencies.push(request.latency);
      this.metrics.consecutiveFailures = 0;
    } else {
      this.metrics.failedRequests++;
      this.metrics.consecutiveFailures++;
      this.metrics.errors.push({
        error: request.error,
        timestamp: Date.now()
      });
      
      // ถ้าล้มเหลวติดกัน 3 ครั้ง ให้ส่ง Alert
      if (this.metrics.consecutiveFailures >= 3) {
        this.triggerAlert('CONSECUTIVE_FAILURES', {
          failures: this.metrics.consecutiveFailures,
          lastError: request.error
        });
      }
    }
    
    // คำนวณ SLA ทุกครั้งที่มี Request ใหม่
    this.checkSLACompliance();
  }

  // ตรวจสอบสุขภาพของ API
  async performHealthCheck() {
    const startTime = Date.now();
    
    try {
      // ส่ง Health Check Request
      const response = await fetch('https://api.holysheep.ai/v1/health', {
        method: 'GET',
        headers: {
          'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY}
        }
      });
      
      const latency = Date.now() - startTime;
      
      if (response.ok) {
        console.log(✅ Health Check OK | Latency: ${latency}ms);
        this.metrics.consecutiveFailures = 0;
      } else {
        console.error(⚠️ Health Check Failed: ${response.status});
        this.triggerAlert('HEALTH_CHECK_FAILED', { status: response.status });
      }
      
    } catch (error) {
      console.error(❌ Health Check Error: ${error.message});
      this.triggerAlert('HEALTH_CHECK_ERROR', { error: error.message });
    }
  }

  // คำนวณ SLA Metrics
  calculateMetrics() {
    const uptime = (this.metrics.successfulRequests / this.metrics.totalRequests) * 100;
    const errorRate = (this.metrics.failedRequests / this.metrics.totalRequests) * 100;
    
    // คำนวณ Percentiles
    const sortedLatencies = [...this.metrics.latencies].sort((a, b) => a - b);
    const p50 = this.percentile(sortedLatencies, 50);
    const p99 = this.percentile(sortedLatencies, 99);
    
    return {
      uptime: uptime.toFixed(2) + '%',
      errorRate: errorRate.toFixed(2) + '%',
      latencyP50: p50 + 'ms',
      latencyP99: p99 + 'ms',
      totalRequests: this.metrics.totalRequests,
      avgLatency: (sortedLatencies.reduce((a, b) => a + b, 0) / sortedLatencies.length || 0).toFixed(2) + 'ms'
    };
  }

  percentile(arr, p) {
    if (arr.length === 0) return 0;
    const index = Math.ceil((p / 100) * arr.length) - 1;
    return arr[Math.max(0, index)];
  }

  // ตรวจสอบว่า SLA เป็นไปตามเป้าหมายหรือไม่
  checkSLACompliance() {
    const current = this.calculateMetrics();
    
    // ตรวจสอบ Uptime
    if (parseFloat(current.uptime) < this.slaTargets.uptime) {
      this.triggerAlert('SLA_BREACH', {
        type: 'uptime',
        target: this.slaTargets.uptime + '%',
        current: current.uptime
      });
    }
    
    // ตรวจสอบ Error Rate
    if (parseFloat(current.errorRate) > this.slaTargets.errorRate) {
      this.triggerAlert('SLA_BREACH', {
        type: 'errorRate',
        target: '< ' + this.slaTargets.errorRate + '%',
        current: current.errorRate
      });
    }
    
    return current;
  }

  // เพิ่ม Alert Callback
  onAlert(callback) {
    this.alertCallbacks.push(callback);
  }

  // ส่ง Alert
  triggerAlert(type, data) {
    const alert = {
      type,
      data,
      timestamp: new Date().toISOString(),
      severity: type === 'CONSECUTIVE_FAILURES' ? 'HIGH' : 'MEDIUM'
    };
    
    console.error(🚨 ALERT [${alert.severity}]: ${type}, data);
    
    // เรียกทุก Callback
    this.alertCallbacks.forEach(cb => cb(alert));
  }

  // หยุด Monitor
  stop() {
    if (this.monitorInterval) {
      clearInterval(this.monitorInterval);
    }
  }
}

// ตัวอย่างการใช้งาน
const monitor = new SLAMonitor({
  uptime: 99.9,
  latencyP99: 500,
  errorRate: 1
});

// ตั้งค่า Alert
monitor.onAlert((alert) => {
  if (alert.type === 'SLA_BREACH') {
    // ส่ง Notification ไปยัง Slack/Discord/Email
    sendNotification(🚨 SLA Breach: ${JSON.stringify(alert)});
  }
});

module.exports = SLAMonitor;

การตั้งค่า Automatic Failover

Failover เป็นระบบสำคัญที่จะสลับไปใช้ API สำรองอัตโนมัติเมื่อ API หลักมีปัญหา ทำให้ระบบไม่ล่มแม้ API หลักจะ down

// failover_manager.js - Automatic Failover between APIs
class FailoverManager {
  constructor(options = {}) {
    this.providers = options.providers || this.getDefaultProviders();
    this.currentProvider = options.primaryProvider || 'holysheep';
    this.failoverThreshold = options.failoverThreshold || 3;  // ล้มเหลวกี่ครั้งถึงสลับ
    this.recoveryThreshold = options.recoveryThreshold || 5;   // สำเร็จกี่ครั้งถึงกลับมา
    this.checkInterval = options.checkInterval || 60000;       // ตรวจสอบทุก 60 วินาที
    
    this.metrics = {};
    this.initializeMetrics();
    
    this.startHealthChecks();
  }

  getDefaultProviders() {
    return {
      'holysheep': {
        name: 'HolySheep',
        baseURL: 'https://api.holysheep.ai/v1',
        apiKey: process.env.HOLYSHEEP_API_KEY,
        priority: 1,
        isActive: true,
        healthScore: 100
      },
      'openai_backup': {
        name: 'OpenAI (Backup)',
        baseURL: 'https://api.openai.com/v1',
        apiKey: process.env.OPENAI_API_KEY,
        priority: 2,
        isActive: false,
        healthScore: 50
      }
    };
  }

  initializeMetrics() {
    Object.keys(this.providers).forEach(key => {
      this.metrics[key] = {
        failures: 0,
        successes: 0,
        lastCheck: null,
        lastSuccess: null,
        lastFailure: null,
        isHealthy: true,
        avgLatency: 0
      };
    });
  }

  // เริ่มตรวจสอบสุขภาพทุก Provider อัตโนมัติ
  startHealthChecks() {
    this.healthCheckTimer = setInterval(async () => {
      await this.checkAllProviders();
      this.attemptRecovery();
    }, this.checkInterval