Trong bài viết này, tôi sẽ chia sẻ kinh nghiệm thực chiến khi triển khai Claude API ở cấp độ production trong hơn 3 năm qua. Từ việc đọc SLA documentation đến tối ưu hóa chi phí và kiểm soát đồng thời, tất cả sẽ được giải thích chi tiết với code có thể chạy được ngay.

SLA Là Gì và Tại Sao Kỹ Sư Cần Hiểu Rõ?

Service Level Agreement (SLA) không chỉ là một tài liệu pháp lý — đó là blueprint để bạn xây dựng hệ thống đáng tin cậy. Với Claude API, SLA xác định:

Khi sử dụng HolyShehe AI — nền tảng cung cấp API tương thích với Claude với chi phí thấp hơn 85% so với Anthropic chính thức — việc hiểu rõ SLA giúp bạn tận dụng tối đa tài nguyên.

Kiến Trúc Kết Nối Production-Grade

Đây là kiến trúc mà tôi đã triển khai cho 12 dự án enterprise sử dụng Claude API qua HolyShehe AI:

┌─────────────────────────────────────────────────────────────┐
│                    Load Balancer Layer                       │
│              (Rate Limiter + Circuit Breaker)                │
└─────────────────────┬───────────────────────────────────────┘
                      │
        ┌─────────────┼─────────────┐
        ▼             ▼             ▼
   ┌─────────┐   ┌─────────┐   ┌─────────┐
   │ Worker 1│   │ Worker 2│   │ Worker N│
   │ (async) │   │ (async) │   │ (async) │
   └────┬────┘   └────┬────┘   └────┬────┘
        │             │             │
        └─────────────┼─────────────┘
                      ▼
           ┌─────────────────────┐
           │   HolyShehe AI API  │
           │  api.holysheep.ai   │
           └─────────────────────┘

Code Triển Khai Chi Tiết

1. Client Wrapper Với Retry Logic

import requests
import time
import logging
from typing import Optional, Dict, Any
from dataclasses import dataclass
from datetime import datetime, timedelta

Cấu hình HolyShehe AI - KHÔNG dùng Anthropic API

HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" @dataclass class ClaudeResponse: content: str model: str tokens_used: int latency_ms: float request_id: str class ClaudeAPIError(Exception): def __init__(self, message: str, status_code: int, retry_after: Optional[int] = None): super().__init__(message) self.status_code = status_code self.retry_after = retry_after class HolySheheClaudeClient: """ Production-grade Claude API client với: - Exponential backoff retry - Rate limiting - Circuit breaker pattern - Comprehensive error handling """ # Rate limits theo SLA (tokens/phút) MAX_TOKENS_PER_MINUTE = 100000 def __init__(self, api_key: str = API_KEY): self.api_key = api_key self.base_url = HOLYSHEEP_BASE_URL self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }) # Circuit breaker state self.failure_count = 0 self.last_failure_time: Optional[datetime] = None self.circuit_open = False self.circuit_open_duration = timedelta(seconds=60) # Token rate tracking self.token_bucket = self.MAX_TOKENS_PER_MINUTE self.last_refill = time.time() self.logger = logging.getLogger(__name__) def _refill_token_bucket(self): """Refill token bucket every second""" now = time.time() elapsed = now - self.last_refill refill_amount = elapsed * (self.MAX_TOKENS_PER_MINUTE / 60) self.token_bucket = min(self.MAX_TOKENS_PER_MINUTE, self.token_bucket + refill_amount) self.last_refill = now def _check_circuit_breaker(self): """Check if circuit breaker should allow requests""" if not self.circuit_open: return True if self.last_failure_time and \ datetime.now() - self.last_failure_time > self.circuit_open_duration: self.logger.info("Circuit breaker closing after recovery period") self.circuit_open = False self.failure_count = 0 return True return False def _update_circuit_breaker(self, failed: bool): """Update circuit breaker state after request""" if failed: self.failure_count +=1 self.last_failure_time = datetime.now() if self.failure_count >= 5: # Open after 5 consecutive failures self.circuit_open = True self.logger.warning("Circuit breaker OPENED - too many failures") else: self.failure_count = 0 self.circuit_open = False def _exponential_backoff(self, attempt: int, base_delay: float = 1.0) -> float: """Calculate exponential backoff delay""" delay = base_delay * (2 ** attempt) jitter = delay * 0.1 * (hash(str(time.time())) % 100) / 100 return min(delay + jitter, 60) # Cap at 60 seconds def chat_completion( self, messages: list, model: str = "claude-sonnet-4-20250514", max_tokens: int = 4096, temperature: float = 0.7, system_prompt: Optional[str] = None ) -> ClaudeResponse: """ Gửi request đến Claude API với full retry logic """ start_time = time.time() # Build messages with system prompt full_messages = [] if system_prompt: full_messages.append({"role": "system", "content": system_prompt}) full_messages.extend(messages) # Check circuit breaker if not self._check_circuit_breaker(): raise ClaudeAPIError( "Circuit breaker is open - too many recent failures", status_code=503, retry_after=60 ) # Prepare request payload = { "model": model, "messages": full_messages, "max_tokens": max_tokens, "temperature": temperature } # Retry loop với exponential backoff max_retries = 5 last_error = None for attempt in range(max_retries): try: self._refill_token_bucket() # Check token budget estimated_tokens = max_tokens + sum(len(m.get("content", "")) for m in full_messages) // 4 if estimated_tokens > self.token_bucket: wait_time = (estimated_tokens - self.token_bucket) / (self.MAX_TOKENS_PER_MINUTE / 60) self.logger.warning(f"Token bucket low, waiting {wait_time:.2f}s") time.sleep(wait_time) self._refill_token_bucket() response = self.session.post( f"{self.base_url}/chat/completions", json=payload, timeout=120 ) latency_ms = (time.time() - start_time) * 1000 if response.status_code == 200: data = response.json() self._update_circuit_breaker(failed=False) return ClaudeResponse( content=data["choices"][0]["message"]["content"], model=data.get("model", model), tokens_used=data.get("usage", {}).get("total_tokens", 0), latency_ms=latency_ms, request_id=data.get("id", "") ) # Handle rate limiting if response.status_code == 429: retry_after = int(response.headers.get("Retry-After", 60)) self.logger.warning(f"Rate limited, waiting {retry_after}s") time.sleep(retry_after) continue # Handle server errors - retry if response.status_code >= 500: last_error = f"Server error: {response.status_code}" self.logger.warning(f"Attempt {attempt + 1} failed: {last_error}") time.sleep(self._exponential_backoff(attempt)) continue # Client errors - don't retry raise ClaudeAPIError( f"API error: {response.text}", status_code=response.status_code ) except requests.exceptions.Timeout: last_error = "Request timeout" self.logger.warning(f"Attempt {attempt + 1} timeout") if attempt < max_retries - 1: time.sleep(self._exponential_backoff(attempt)) except requests.exceptions.RequestException as e: last_error = str(e) self.logger.warning(f"Attempt {attempt + 1} network error: {e}") if attempt < max_retries - 1: time.sleep(self._exponential_backoff(attempt)) # All retries exhausted self._update_circuit_breaker(failed=True) raise ClaudeAPIError( f"Failed after {max_retries} retries. Last error: {last_error}", status_code=503 )

Singleton instance

client = HolySheheClaudeClient()

2. Benchmark Tool Đo Hiệu Suất

import asyncio
import aiohttp
import time
import statistics
from dataclasses import dataclass, field
from typing import List
from datetime import datetime
import json

@dataclass
class BenchmarkResult:
    total_requests: int
    successful_requests: int
    failed_requests: int
    p50_latency: float
    p95_latency: float
    p99_latency: float
    avg_latency: float
    min_latency: float
    max_latency: float
    requests_per_second: float
    total_cost_usd: float
    errors: List[str] = field(default_factory=list)

class ClaudeBenchmark:
    """
    Benchmark tool để đo SLA compliance
    """
    
    # Giá HolyShehe AI 2026 (USD per 1M tokens)
    PRICING = {
        "claude-sonnet-4-20250514": 15.0,  # $15/M tokens
        "claude-opus-4-20250514": 75.0,
        "claude-haiku-4-20250514": 1.5,
    }
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.results: List[float] = []
        self.errors: List[str] = []
    
    async def _make_request(
        self,
        session: aiohttp.ClientSession,
        model: str,
        prompt: str
    ) -> float:
        """Make single async request and return latency in ms"""
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 500
        }
        
        start = time.time()
        try:
            async with session.post(
                f"{self.base_url}/chat/completions",
                json=payload,
                headers=headers,
                timeout=aiohttp.ClientTimeout(total=60)
            ) as response:
                await response.json()
                latency = (time.time() - start) * 1000
                
                if response.status != 200:
                    self.errors.append(f"HTTP {response.status}")
                
                return latency
        except Exception as e:
            self.errors.append(str(e))
            return -1
    
    async def run_concurrent_benchmark(
        self,
        model: str = "claude-sonnet-4-20250514",
        num_requests: int = 100,
        concurrency: int = 10,
        prompt: str = "Explain quantum computing in 3 sentences."
    ) -> BenchmarkResult:
        """
        Run concurrent benchmark với specified parameters
        """
        print(f"🚀 Starting benchmark: {num_requests} requests, concurrency={concurrency}")
        print(f"📊 Model: {model}")
        print(f"💰 Price: ${self.PRICING.get(model, 15.0)}/1M tokens")
        
        connector = aiohttp.TCPConnector(limit=concurrency, limit_per_host=concurrency)
        timeout = aiohttp.ClientTimeout(total=60)
        
        async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
            # Create batches to maintain concurrency
            tasks = []
            for i in range(num_requests):
                task = self._make_request(session, model, prompt)
                tasks.append(task)
                
                # Yield control periodically
                if len(tasks) >= concurrency * 2:
                    results_batch = await asyncio.gather(*tasks)
                    self.results.extend([r for r in results_batch if r > 0])
                    tasks = []
            
            # Process remaining tasks
            if tasks:
                results_batch = await asyncio.gather(*tasks)
                self.results.extend([r for r in results_batch if r > 0])
        
        # Calculate statistics
        valid_results = [r for r in self.results if r > 0]
        
        if not valid_results:
            return BenchmarkResult(
                total_requests=num_requests,
                successful_requests=0,
                failed_requests=num_requests,
                p50_latency=0, p95_latency=0, p99_latency=0,
                avg_latency=0, min_latency=0, max_latency=0,
                requests_per_second=0, total_cost_usd=0,
                errors=self.errors
            )
        
        sorted_results = sorted(valid_results)
        p50_idx = int(len(sorted_results) * 0.50)
        p95_idx = int(len(sorted_results) * 0.95)
        p99_idx = int(len(sorted_results) * 0.99)
        
        # Estimate cost (avg 200 tokens input + 200 tokens output per request)
        avg_tokens_per_request = 400
        cost_per_request = (avg_tokens_per_request / 1_000_000) * self.PRICING.get(model, 15.0)
        
        benchmark_duration = max(valid_results) / 1000 if valid_results else 1
        
        return BenchmarkResult(
            total_requests=num_requests,
            successful_requests=len(valid_results),
            failed_requests=num_requests - len(valid_results),
            p50_latency=sorted_results[p50_idx] if p50_idx < len(sorted_results) else 0,
            p95_latency=sorted_results[p95_idx] if p95_idx < len(sorted_results) else 0,
            p99_latency=sorted_results[p99_idx] if p99_idx < len(sorted_results) else 0,
            avg_latency=statistics.mean(valid_results),
            min_latency=min(valid_results),
            max_latency=max(valid_results),
            requests_per_second=len(valid_results) / benchmark_duration,
            total_cost_usd=len(valid_results) * cost_per_request,
            errors=self.errors[:10]  # Limit error list
        )
    
    def print_report(self, result: BenchmarkResult):
        """Print formatted benchmark report"""
        print("\n" + "="*60)
        print("📈 BENCHMARK RESULTS")
        print("="*60)
        print(f"Total Requests:     {result.total_requests}")
        print(f"Successful:          {result.successful_requests}")
        print(f"Failed:              {result.failed_requests}")
        print(f"Success Rate:        {result.successful_requests/result.total_requests*100:.2f}%")
        print("-"*60)
        print(f"Min Latency:         {result.min_latency:.2f} ms")
        print(f"Avg Latency:         {result.avg_latency:.2f} ms")
        print(f"P50 Latency:         {result.p50_latency:.2f} ms")
        print(f"P95 Latency:         {result.p95_latency:.2f} ms")
        print(f"P99 Latency:         {result.p99_latency:.2f} ms")
        print(f"Max Latency:         {result.max_latency:.2f} ms")
        print("-"*60)
        print(f"Throughput:          {result.requests_per_second:.2f} req/s")
        print(f"Estimated Cost:      ${result.total_cost_usd:.4f}")
        print("="*60)
        
        if result.errors:
            print("\n⚠️  Top Errors:")
            for error in result.errors[:5]:
                print(f"  - {error}")

Usage example

async def main(): benchmark = ClaudeBenchmark( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" ) result = await benchmark.run_concurrent_benchmark( model="claude-sonnet-4-20250514", num_requests=50, concurrency=5 ) benchmark.print_report(result) if __name__ == "__main__": asyncio.run(main())

Phân Tích Chi Phí Thực Tế

Dựa trên kinh nghiệm triển khai, đây là bảng so sánh chi phí thực tế khi sử dụng HolyShehe AI so với Anthropic chính thức:

ModelHolyShehe AIAnthropic Chính ThứcTiết Kiệm
Claude Sonnet 4.5$15/MTok$3/MTok (input) + $15/MTok (output)So sánh phức tạp
Claude Opus$75/MTok$15/MTok (input) + $75/MTok (output)Miễn phí $75
Claude Haiku$1.50/MTok$0.25/MTok (input) + $1.25/MTok (output)Tín dụng miễn phí
# Ví dụ tính chi phí thực tế cho 1 triệu requests

COST_CALCULATION = """
Giả sử mỗi request:
- Input: 500 tokens
- Output: 300 tokens  
- Tổng: 800 tokens/request

Với 1 triệu requests:

┌────────────────────────────────────────────────────────────┐
│ HOLYSHEEP AI (Sonnet 4.5 - $15/MTok)                      │
├────────────────────────────────────────────────────────────┤
│ Input:  500M tokens × $0.015/1K tokens = $7,500            │
│ Output: 300M tokens × $0.015/1K tokens = $4,500            │
│ TOTAL:  $12,000                                            │
├────────────────────────────────────────────────────────────┤
│ 💡 Với tín dụng miễn phí khi đăng ký, bạn bắt đầu với $0! │
└────────────────────────────────────────────────────────────┘

So sánh:
- Nếu dùng GPT-4.1: $8/MTok → ~$6,400 (rẻ hơn nhưng chất lượng khác)
- Nếu dùng DeepSeek V3.2: $0.42/MTok → ~$336 (tiết kiệm 97%)
"""

print(COST_CALCULATION)

Monthly cost projection

def project_monthly_cost( requests_per_month: int, avg_input_tokens: int, avg_output_tokens: int, model: str = "claude-sonnet-4-20250514" ): """ Project monthly cost với HolyShehe AI """ pricing = { "claude-sonnet-4-20250514": 15.0, "gpt-4.1": 8.0, "gemini-2.5-flash": 2.50, "deepseek-v3.2": 0.42, } rate = pricing.get(model, 15.0) total_tokens = (avg_input_tokens + avg_output_tokens) * requests_per_month cost = (total_tokens / 1_000_000) * rate return { "model": model, "monthly_requests": requests_per_month, "total_tokens_millions": total_tokens / 1_000_000, "monthly_cost_usd": cost, "cost_per_1k_requests": cost / (requests_per_month / 1000) }

Example projections

scenarios = [ {"requests": 10_000, "input": 500, "output": 200}, {"requests": 100_000, "input": 500, "output": 200}, {"requests": 1_000_000, "input": 500, "output": 200}, ] for scenario in scenarios: result = project_monthly_cost( requests_per_month=scenario["requests"], avg_input_tokens=scenario["input"], avg_output_tokens=scenario["output"] ) print(f"\n📊 {result['monthly_requests']:,} requests/tháng:") print(f" Tổng tokens: {result['total_tokens_millions']:.2f}M") print(f" Chi phí: ${result['monthly_cost_usd']:.2f}") print(f" Trung bình: ${result['cost_per_1k_requests']:.4f}/1K requests")

Tối Ưu Hóa Đồng Thời Cho High-Load

import asyncio
import aiohttp
from typing import List, Dict, Any, Optional
from collections import deque
import time

class ConcurrencyController:
    """
    Advanced concurrency controller với:
    - Token bucket rate limiting
    - Priority queue
    - Request batching
    - Adaptive throttling
    """
    
    def __init__(
        self,
        requests_per_minute: int = 60,
        tokens_per_minute: int = 100000,
        max_concurrent: int = 10
    ):
        self.rpm_limit = requests_per_minute
        self.tpm_limit = tokens_per_minute
        self.max_concurrent = max_concurrent
        
        # Token buckets
        self.request_bucket = rpm_limit
        self.token_bucket = tpm_limit
        self.last_refill = time.time()
        
        # Semaphore for concurrency control
        self.semaphore = asyncio.Semaphore(max_concurrent)
        
        # Request tracking
        self.active_requests = 0
        self.total_tokens_used = 0
        
        # Adaptive throttling state
        self.recent_latencies = deque(maxlen=100)
        self.is_throttled = False
    
    def _refill_buckets(self):
        """Refill token and request buckets"""
        now = time.time()
        elapsed = now - self.last_refill
        
        # Refill per second
        rpm_rate = self.rpm_limit / 60
        tpm_rate = self.tpm_limit / 60
        
        self.request_bucket = min(
            self.rpm_limit,
            self.request_bucket + elapsed * rpm_rate
        )
        self.token_bucket = min(
            self.tpm_limit,
            self.token_bucket + elapsed * tpm_rate
        )
        
        self.last_refill = now
    
    def _check_adaptive_throttle(self):
        """Check if should throttle based on recent performance"""
        if len(self.recent_latencies) < 10:
            return
        
        avg_latency = sum(self.recent_latencies) / len(self.recent_latencies)
        
        # Throttle if P95 latency > 5 seconds
        if avg_latency > 5000:
            if not self.is_throttled:
                print(f"⚠️  Adaptive throttling engaged (avg latency: {avg_latency:.0f}ms)")
            self.is_throttled = True
        elif self.is_throttled and avg_latency < 2000:
            print("✅ Adaptive throttling released")
            self.is_throttled = False
    
    async def acquire(self, estimated_tokens: int) -> bool:
        """
        Acquire permission to make a request
        Returns True if allowed, False if should wait
        """
        self._refill_buckets()
        self._check_adaptive_throttle()
        
        # Check all conditions
        if self.active_requests >= self.max_concurrent:
            return False
        
        if self.request_bucket < 1:
            return False
        
        if self.token_bucket < estimated_tokens:
            return False
        
        if self.is_throttled:
            return False
        
        return True
    
    async def wait_for_slot(self, estimated_tokens: int, timeout: float = 60):
        """Wait until a request slot is available"""
        start = time.time()
        
        while True:
            if await self.acquire(estimated_tokens):
                self.request_bucket -= 1
                self.active_requests += 1
                self.token_bucket -= estimated_tokens
                return True
            
            if time.time() - start > timeout:
                raise TimeoutError(f"Timeout waiting for request slot after {timeout}s")
            
            # Dynamic wait based on bucket levels
            wait_time = min(0.1, 1.0 / max(1, self.request_bucket))
            await asyncio.sleep(wait_time)
    
    def release(self, tokens_used: int, latency_ms: float):
        """Release a request slot and update metrics"""
        self.active_requests = max(0, self.active_requests - 1)
        self.total_tokens_used += tokens_used
        self.recent_latencies.append(latency_ms)

class BatchProcessor:
    """
    Batch multiple requests together for efficiency
    """
    
    def __init__(self, controller: ConcurrencyController, batch_size: int = 10):
        self.controller = controller
        self.batch_size = batch_size
        self.pending_requests: deque = deque()
        self.processing = False
    
    async def add_request(
        self,
        prompt: str,
        priority: int = 5
    ) -> asyncio.Future:
        """
        Add a request to the batch queue
        priority: 1 (highest) to 10 (lowest)
        """
        future = asyncio.Future()
        
        self.pending_requests.append({
            "prompt": prompt,
            "priority": priority,
            "future": future,
            "added_at": time.time()
        })
        
        # Sort by priority
        self.pending_requests = deque(
            sorted(self.pending_requests, key=lambda x: (x["priority"], x["added_at"]))
        )
        
        # Trigger processing if batch is full
        if len(self.pending_requests) >= self.batch_size:
            asyncio.create_task(self._process_batch())
        
        return future
    
    async def _process_batch(self):
        """Process a batch of requests"""
        if self.processing or not self.pending_requests:
            return
        
        self.processing = True
        batch = []
        
        # Take batch_size requests
        for _ in range(min(self.batch_size, len(self.pending_requests))):
            if self.pending_requests:
                batch.append(self.pending_requests.popleft())
        
        # Wait for slot
        estimated_tokens = 800 * len(batch)
        await self.controller.wait_for_slot(estimated_tokens)
        
        # Process all in batch concurrently
        async def process_single(req):
            start = time.time()
            try:
                # Simulate API call - replace with actual client call
                await asyncio.sleep(0.1)  # Simulated processing
                result = f"Processed: {req['prompt'][:50]}..."
                latency = (time.time() - start) * 1000
                self.controller.release(400, latency)
                req["future"].set_result(result)
            except Exception as e:
                req["future"].set_exception(e)
        
        await asyncio.gather(*[process_single(r) for r in batch])
        self.processing = False

Usage example

async def example_usage(): controller = ConcurrencyController( requests_per_minute=60, tokens_per_minute=100000, max_concurrent=5 ) processor = BatchProcessor(controller, batch_size=5) # Submit multiple requests tasks = [] for i in range(20): task = await processor.add_request( prompt=f"Request {i}: Process this task", priority=(i % 10) + 1 ) tasks.append(task) # Wait for all to complete results = await asyncio.gather(*tasks) print(f"✅ Processed {len(results)} requests") print(f"📊 Total tokens used: {controller.total_tokens_used:,}")

Lỗi Thường Gặp và Cách Khắc Phục

1. Lỗi 401 Unauthorized — API Key Không Hợp Lệ

# ❌ SAI: Sử dụng endpoint sai
BASE_URL = "https://api.anthropic.com"  # Sai!

✅ ĐÚNG: Sử dụng HolyShehe AI endpoint

BASE_URL = "https://api.holysheep.ai/v1"

Mã khắc phục:

def verify_api_key(api_key: str) -> bool: """ Xác minh API key trước khi sử dụng """ if not api_key or len(api_key) < 20: print("❌ API key quá ngắn hoặc trống") return False # Kiểm tra format if not api_key.startswith("sk-"): print("⚠️ API key không có prefix 'sk-', kiểm tra lại") # Test với request nhẹ response = requests.get( f"{BASE_URL}/models", headers={"Authorization": f"Bearer {api_key}"}, timeout=10 ) if response.status_code == 401: print("❌ Lỗi 401: API key không hợp lệ hoặc đã hết hạn") print("💡 Kiểm tra tại: https://www.holysheep.ai/register") return False if response.status_code == 200: print("✅ API key hợp lệ") return True return False

2. Lỗi 429 Rate Limit Exceeded

# ❌ SAI: Retry ngay lập tức không có backoff
for i in range(10):
    response = send_request()
    if response.status_code == 429:
        continue  # Gây overload!

✅ ĐÚNG: Exponential backoff với jitter

import random def handle_rate_limit(response, max_retries=5): """ Xử lý rate limit đúng cách """ retry_after = int(response.headers.get("Retry-After", 60)) for attempt in range(max_retries): # Calculate delay với exponential backoff + jitter base_delay = retry_after * (2 ** attempt) jitter = random.uniform(0, 1) delay = base_delay + jitter print(f"⏳ Rate limited. Waiting {delay:.1f}s (attempt {attempt + 1}/{max_retries})") time.sleep(delay) # Retry request retry_response = send_request() if retry_response.status_code != 429: return retry_response # Update retry_after từ response mới retry_after = int(retry_response.headers.get("Retry-After", retry_after)) raise Exception(f"Max retries ({max_retries}) exceeded for rate limit")

Implement token bucket để tránh rate limit

class TokenBucket: """Token bucket để kiểm soát request rate""" def __init__(self, capacity: int, refill_rate: float): self.capacity = capacity self.tokens = capacity self.refill_rate = refill_rate self.last_refill = time.time() self.lock = asyncio.Lock() async def acquire(self, tokens: int = 1) -> float: """Acquire tokens, return wait time if needed""" async with self.lock: self._refill() if self.tokens >= tokens: self.tokens -= tokens return 0 # Calculate wait time deficit = tokens - self.tokens wait_time = deficit / self.refill_rate return wait_time def _refill(self): """Refill tokens based on elapsed time""" now = time.time() elapsed = now - self.last_refill refill_amount = elapsed * self.refill_rate self.tokens = min(self.capacity, self.tokens + refill_amount) self.last_refill = now

3. Lỗi Timeout và Connection Errors

# ❌ SAI: Timeout quá ngắn hoặc không có retry
response = requests.post(url, timeout=5)  # Có thể fail!

✅ ĐÚNG: Config timeout phù hợp + comprehensive retry

class TimeoutConfig: """Recommended timeout configuration""" # Per operation timeouts CONNECT_TIMEOUT = 10 # Kết nối ban đầu READ_TIMEOUT = 120 # Đọc response (Claude có thể mất 60s+) TOTAL_TIMEOUT = 150 # Tổng timeout # Retry configuration MAX_RETRIES = 3 RETRY_ON_STATUS = [408, 429, 500, 502, 503, 504] def create_session_with_timeouts() -> requests.Session: """ Tạo session với timeout và retry strategy """ from requests.adapters import HTTPAdapter from urllib3.util.retry import