本番環境で大規模言語モデル(LLM)を運用する際、同時に複数のリクエストを処理する必要があるケースは必ず訪れます。しかし、すべてのAI APIプロバイダーは同時接続数(concurrency limit)に上限を設けており、この制限がシステム全体のスループットを制約するボトルネックとなります。
私は複数の本番プロジェクトで、この同時接続数制限导致的パフォーマンス問題を日々最適化してきました。本稿では、代表的な4つの突破手法を архитектура設計からパフォーマンス、そしてコスト最適化の観点から深く比較し、あなたのユースケースに最適な選択を指南します。
同時接続数制限が生まれる根本原因
AI APIプロバイダーが同時接続数に制限を設ける理由は主に3つです:
- リソース保護:GPUクラスタの過負荷を防止
- 公平性確保:すべてのユーザーに安定したサービスを提供
- コスト管理:予測可能なインフラコストを維持
この制限を突破しないまま高負荷運用すると、リクエストが503 Service Unavailableで拒否され、ユーザー体験が大きく損なわれます。
同時接続数制限突破の4つの主要アプローチ
1. リクエストキューイング(Request Queuing)
最もシンプルな手法です。リクエストをFIFOキューに溜め込み、プロバイダーの同時接続数に合わせて逐次処理します。
import asyncio
import aiohttp
from collections import deque
from dataclasses import dataclass, field
from typing import Optional
import time
@dataclass
class QueuedRequest:
prompt: str
result: Optional[str] = None
error: Optional[str] = None
enqueued_at: float = field(default_factory=time.time)
completed_at: Optional[float] = None
class RequestQueue:
def __init__(
self,
api_key: str,
base_url: str = "https://api.holysheep.ai/v1",
max_concurrent: int = 5,
rate_limit_per_minute: int = 60
):
self.api_key = api_key
self.base_url = base_url
self.max_concurrent = max_concurrent
self.rate_limit = rate_limit_per_minute / 60 # per second
self.queue: deque[QueuedRequest] = deque()
self.semaphore = asyncio.Semaphore(max_concurrent)
self.last_request_time = 0
self._lock = asyncio.Lock()
async def _rate_limit_wait(self):
"""レート制限を遵守するための待機"""
async with self._lock:
min_interval = 1.0 / self.rate_limit
elapsed = time.time() - self.last_request_time
if elapsed < min_interval:
await asyncio.sleep(min_interval - elapsed)
self.last_request_time = time.time()
async def _execute_request(
self,
session: aiohttp.ClientSession,
request: QueuedRequest
) -> QueuedRequest:
async with self.semaphore:
await self._rate_limit_wait()
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "gpt-4.1",
"messages": [{"role": "user", "content": request.prompt}],
"max_tokens": 1000
}
try:
async with session.post(
f"{self.base_url}/chat/completions",
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=60)
) as response:
if response.status == 200:
data = await response.json()
request.result = data["choices"][0]["message"]["content"]
else:
error_text = await response.text()
request.error = f"HTTP {response.status}: {error_text}"
except Exception as e:
request.error = str(e)
request.completed_at = time.time()
return request
async def enqueue(self, prompt: str) -> QueuedRequest:
"""リクエストをキューに追加"""
request = QueuedRequest(prompt=prompt)
self.queue.append(request)
return request
async def process_all(
self,
progress_callback: Optional[callable] = None
) -> list[QueuedRequest]:
"""キュー内の全リクエストを処理"""
connector = aiohttp.TCPConnector(limit=self.max_concurrent)
async with aiohttp.ClientSession(connector=connector) as session:
tasks = []
for request in self.queue:
task = asyncio.create_task(
self._execute_request(session, request)
)
tasks.append(task)
if progress_callback:
progress_callback(len(tasks), len(self.queue))
results = await asyncio.gather(*tasks)
return list(results)
使用例
async def main():
queue = RequestQueue(
api_key="YOUR_HOLYSHEEP_API_KEY",
max_concurrent=5,
rate_limit_per_minute=60
)
# 100件のリクエストをキューに追加
for i in range(100):
await queue.enqueue(f"リポート {i+1} のサマリーを生成してください")
# 進捗表示付きで処理
def show_progress(completed, total):
print(f"進捗: {completed}/{total} ({completed*100//total}%)")
results = await queue.process_all(progress_callback=show_progress)
# 結果の確認
successful = sum(1 for r in results if r.result)
failed = sum(1 for r in results if r.error)
avg_time = sum(
r.completed_at - r.enqueued_at
for r in results if r.completed_at
) / len(results)
print(f"成功: {successful}, 失敗: {failed}")
print(f"平均処理時間: {avg_time:.2f}秒")
asyncio.run(main())
この手法の長所は実装のシンプルさです。短所はチェーン全体の処理時間が接続数上限に律速される点です。
2. リクエストバッチング(Request Batching)
複数のリクエストを1つのバッチに統合し、1回のAPI呼び出しで処理します。これは特にHolySheep AIのbatch APIで効率的に実装できます。
import asyncio
import aiohttp
import json
from typing import list
from dataclasses import dataclass
import hashlib
@dataclass
class BatchJob:
job_id: str
prompts: list[str]
results: list[Optional[str]] = None
status: str = "pending"
class BatchProcessor:
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.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def _create_job_id(self, prompts: list[str]) -> str:
"""プロンプトのハッシュからjob_idを生成"""
content = json.dumps(prompts, sort_keys=True)
return hashlib.sha256(content.encode()).hexdigest()[:16]
async def create_batch_job(self, prompts: list[str]) -> str:
"""
バッチジョブを作成(HolySheep batch API使用)
最大50件のプロンプトを1バッチにまとめ可能
"""
job_id = self._create_job_id(prompts)
# HolySheep Batch APIへのリクエスト構築
requests = []
for idx, prompt in enumerate(prompts):
requests.append({
"custom_id": f"req_{job_id}_{idx}",
"method": "POST",
"url": "/chat/completions",
"body": {
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "あなたは有能なアシスタントです。"},
{"role": "user", "content": prompt}
],
"max_tokens": 500
}
})
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as session:
# -batch endpointにリクエスト
async with session.post(
f"{self.base_url}/batches",
json={"input_file_content": requests},
headers=self.headers
) as response:
if response.status == 200:
data = await response.json()
return data.get("id", job_id)
else:
error = await response.text()
raise RuntimeError(f"Batch creation failed: {error}")
async def get_batch_results(
self,
batch_id: str,
timeout: int = 300
) -> list[dict]:
"""バッチジョブの結果を取得"""
connector = aiohttp.TCPConnector(limit=5)
start_time = asyncio.get_event_loop().time()
async with aiohttp.ClientSession(connector=connector) as session:
while True:
async with session.get(
f"{self.base_url}/batches/{batch_id}",
headers=self.headers
) as response:
data = await response.json()
status = data.get("status")
if status == "completed":
# 結果ファイルを取得
output_file_id = data.get("output_file_id")
return await self._fetch_results(session, output_file_id)
elif status in ("failed", "expired", "cancelled"):
raise RuntimeError(f"Batch job {status}: {data.get('error')}")
# ポーリング間隔を動的に調整
await asyncio.sleep(min(10, (asyncio.get_event_loop().time() - start_time) / 10))
if asyncio.get_event_loop().time() - start_time > timeout:
raise TimeoutError(f"Batch job timeout after {timeout}s")
async def _fetch_results(
self,
session: aiohttp.ClientSession,
file_id: str
) -> list[dict]:
"""結果ファイルをダウンロードしてパース"""
async with session.get(
f"{self.base_url}/files/{file_id}/content",
headers=self.headers
) as response:
content = await response.text()
return [json.loads(line) for line in content.strip().split("\n") if line]
最適なバッチサイズの決定ロジック
def calculate_optimal_batch_size(
avg_prompt_tokens: int,
avg_output_tokens: int,
model_context_window: int = 128000
) -> int:
"""
コンテキストウィンドウに基づいて最適なバッチサイズを計算
"""
tokens_per_request = avg_prompt_tokens + avg_output_tokens
# 安全係数(システムプロンプト、JSONフォーマットオーバーヘッド)
safety_factor = 0.8
effective_window = model_context_window * safety_factor
optimal_batch = max(1, int(effective_window / tokens_per_request))
# HolySheepのバッチ制限(最大50件)
return min(optimal_batch, 50)
使用例
async def main():
processor = BatchProcessor(api_key="YOUR_HOLYSHEEP_API_KEY")
# 1000件のプロンプトを処理
prompts = [f"質問 {i}: {生成したい内容}" for i in range(1000)]
# 最適なバッチサイズを計算
batch_size = calculate_optimal_batch_size(
avg_prompt_tokens=200,
avg_output_tokens=300
)
print(f"最適バッチサイズ: {batch_size}")
# バッチに分割して処理
batches = [prompts[i:i+batch_size] for i in range(0, len(prompts), batch_size)]
all_results = []
for idx, batch in enumerate(batches):
print(f"バッチ {idx+1}/{len(batches)} を処理中...")
batch_id = await processor.create_batch_job(batch)
results = await processor.get_batch_results(batch_id)
all_results.extend(results)
print(f"合計 {len(all_results)} 件の結果を取得")
asyncio.run(main())
バッチ処理の強みはAPI呼び出し回数を劇的に減らせることです。HolySheep AIのbatch APIなら25%安い料金で処理できます。
3. 分散フォールトトレラントプロキシ
複数のAPIキーを異なるプロバイダーに分散させ、自動フェイルオーバー机制を構築します。
import asyncio
import aiohttp
from dataclasses import dataclass, field
from typing import Optional
from enum import Enum
import time
from collections import defaultdict
class Provider(Enum):
HOLYSHEEP = "holysheep"
OPENAI = "openai" # フォールバック用
ANTHROPIC = "anthropic"
@dataclass
class ProviderConfig:
name: Provider
base_url: str
api_key: str
rate_limit: int # requests per minute
current_load: int = 0
error_count: int = 0
last_error_time: float = 0
latency_avg: float = 0
@dataclass
class RequestResult:
provider: Provider
success: bool
data: Optional[dict] = None
error: Optional[str] = None
latency_ms: float = 0
class DistributedProxy:
def __init__(self):
self.providers: dict[Provider, ProviderConfig] = {}
self.stats = defaultdict(lambda: {"success": 0, "failure": 0, "latencies": []})
self._health_check_interval = 60
self._circuit_breaker_threshold = 5
self._circuit_breaker_cooldown = 300 # 5分
def add_provider(
self,
name: Provider,
api_key: str,
rate_limit: int,
base_url: Optional[str] = None
):
"""プロバイダーを追加(HolySheepがデフォルト)"""
if base_url is None:
if name == Provider.HOLYSHEEP:
base_url = "https://api.holysheep.ai/v1"
elif name == Provider.OPENAI:
base_url = "https://api.openai.com/v1"
elif name == Provider.ANTHROPIC:
base_url = "https://api.anthropic.com/v1"
self.providers[name] = ProviderConfig(
name=name,
base_url=base_url,
api_key=api_key,
rate_limit=rate_limit
)
def _is_provider_available(self, provider: ProviderConfig) -> bool:
"""サーキットブレーカー状態をチェック"""
if provider.error_count >= self._circuit_breaker_threshold:
if time.time() - provider.last_error_time < self._circuit_breaker_cooldown:
return False
# クーリングダウン後のリセット
provider.error_count = 0
return True
def _select_provider(self) -> Optional[ProviderConfig]:
"""Least-Connections方式で最適なプロバイダーを選択"""
available = [
p for p in self.providers.values()
if self._is_provider_available(p)
]
if not available:
return None
# 最小負荷のプロバイダーを選択
return min(available, key=lambda p: p.current_load)
async def _call_api(
self,
provider: ProviderConfig,
payload: dict
) -> RequestResult:
"""单个プロバイダーへのAPI呼び出し"""
start_time = time.time()
headers = {
"Authorization": f"Bearer {provider.api_key}",
"Content-Type": "application/json"
}
try:
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.post(
f"{provider.base_url}/chat/completions",
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=30)
) as response:
latency = (time.time() - start_time) * 1000
if response.status == 200:
data = await response.json()
provider.latency_avg = (provider.latency_avg * 0.9 + latency * 0.1)
return RequestResult(
provider=provider.name,
success=True,
data=data,
latency_ms=latency
)
elif response.status == 429:
# レートリミット時の指数バックオフ
await asyncio.sleep(2 ** provider.current_load)
return RequestResult(
provider=provider.name,
success=False,
error="Rate limited"
)
else:
provider.error_count += 1
provider.last_error_time = time.time()
return RequestResult(
provider=provider.name,
success=False,
error=f"HTTP {response.status}"
)
except Exception as e:
provider.error_count += 1
provider.last_error_time = time.time()
return RequestResult(
provider=provider.name,
success=False,
error=str(e)
)
async def chat_completion(
self,
messages: list[dict],
model: str = "gpt-4.1"
) -> RequestResult:
"""分散フォールトオーバー付きでchat completionを実行"""
payload = {
"model": model,
"messages": messages,
"max_tokens": 1000
}
max_retries = len(self.providers)
for attempt in range(max_retries):
provider = self._select_provider()
if not provider:
return RequestResult(
provider=Provider.HOLYSHEEP, # フォールバック先
success=False,
error="All providers unavailable"
)
provider.current_load += 1
try:
result = await self._call_api(provider, payload)
if result.success:
self.stats[provider.name]["success"] += 1
self.stats[provider.name]["latencies"].append(result.latency_ms)
return result
self.stats[provider.name]["failure"] += 1
# 別のプロバイダーでリトライ
if attempt < max_retries - 1:
await asyncio.sleep(0.5 * (attempt + 1))
finally:
provider.current_load = max(0, provider.current_load - 1)
return RequestResult(
provider=Provider.HOLYSHEEP,
success=False,
error="All retry attempts failed"
)
def get_stats(self) -> dict:
"""現在の負荷分散統計を返す"""
return {
name: {
"load": p.current_load,
"error_count": p.error_count,
"avg_latency_ms": round(p.latency_avg, 2),
"success_rate": (
self.stats[name]["success"] /
max(1, self.stats[name]["success"] + self.stats[name]["failure"])
)
}
for name, p in self.providers.items()
}
使用例
async def main():
proxy = DistributedProxy()
# HolySheepを主プロバイダーとして追加
proxy.add_provider(
name=Provider.HOLYSHEEP,
api_key="YOUR_HOLYSHEEP_API_KEY",
rate_limit=1000, # ¥1=$1のレート
base_url="https://api.holysheep.ai/v1"
)
# フォールバック用プロバイダー(必要に応じて)
# proxy.add_provider(Provider.OPENAI, "backup-key", 500)
# 100件の同時リクエストをテスト
tasks = [
proxy.chat_completion(
messages=[{"role": "user", "content": f"テストプロンプト {i}"}],
model="gpt-4.1"
)
for i in range(100)
]
results = await asyncio.gather(*tasks, return_exceptions=True)
successful = sum(1 for r in results if isinstance(r, RequestResult) and r.success)
failed = sum(1 for r in results if isinstance(r, RequestResult) and not r.success)
print(f"成功: {successful}, 失敗: {failed}")
print(f"統計: {proxy.get_stats()}")
asyncio.run(main())
4. プロダクショングレードの 워ーカープール
RedisやBullMQを用いたエンタープライズレベルのリクエスト管理です。
import asyncio
import aiohttp
from dataclasses import dataclass
from typing import Optional, Callable
import uuid
import json
from enum import Enum
class JobStatus(Enum):
PENDING = "pending"
PROCESSING = "processing"
COMPLETED = "completed"
FAILED = "failed"
@dataclass
class Job:
job_id: str
prompt: str
status: JobStatus = JobStatus.PENDING
result: Optional[dict] = None
error: Optional[str] = None
priority: int = 0
created_at: float = 0
started_at: Optional[float] = None
completed_at: Optional[float] = None
注:実際の本番環境ではRedis + BullMQを使用してください
ここではデモ用のインプロセsimplementation
class InMemoryJobQueue:
def __init__(self, max_concurrent: int = 10):
self.max_concurrent = max_concurrent
self.jobs: dict[str, Job] = {}
self.pending_queue: list[str] = []
self.processing: set[str] = set()
self.completed_results: dict[str, Job] = {}
self._lock = asyncio.Lock()
def enqueue(
self,
prompt: str,
priority: int = 0,
job_id: Optional[str] = None
) -> str:
job_id = job_id or str(uuid.uuid4())
job = Job(
job_id=job_id,
prompt=prompt,
priority=priority
)
self.jobs[job_id] = job
# 優先度順に挿入
inserted = False
for i, qid in enumerate(self.pending_queue):
if self.jobs[qid].priority < priority:
self.pending_queue.insert(i, job_id)
inserted = True
break
if not inserted:
self.pending_queue.append(job_id)
return job_id
async def dequeue(self) -> Optional[Job]:
async with self._lock:
if len(self.processing) >= self.max_concurrent:
return None
if not self.pending_queue:
return None
job_id = self.pending_queue.pop(0)
job = self.jobs[job_id]
job.status = JobStatus.PROCESSING
self.processing.add(job_id)
return job
async def complete(self, job_id: str, result: dict):
async with self._lock:
if job_id in self.processing:
self.processing.remove(job_id)
job = self.jobs[job_id]
job.status = JobStatus.COMPLETED
job.result = result
self.completed_results[job_id] = job
async def fail(self, job_id: str, error: str):
async with self._lock:
if job_id in self.processing:
self.processing.remove(job_id)
job = self.jobs[job_id]
job.status = JobStatus.FAILED
job.error = error
def get_result(self, job_id: str) -> Optional[Job]:
return self.completed_results.get(job_id)
class WorkerPool:
def __init__(
self,
queue: InMemoryJobQueue,
api_key: str,
base_url: str = "https://api.holysheep.ai/v1",
num_workers: int = 5
):
self.queue = queue
self.api_key = api_key
self.base_url = base_url
self.num_workers = num_workers
self.workers: list[asyncio.Task] = []
self._running = False
async def worker_loop(self, worker_id: int):
"""单个ワーカープロセス"""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
connector = aiohttp.TCPConnector(limit=5)
async with aiohttp.ClientSession(connector=connector) as session:
while self._running:
job = await self.queue.dequeue()
if job is None:
await asyncio.sleep(0.1)
continue
payload = {
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "簡潔かつ正確に回答してください。"},
{"role": "user", "content": job.prompt}
],
"max_tokens": 800,
"temperature": 0.7
}
try:
async with session.post(
f"{self.base_url}/chat/completions",
json=payload,
headers=headers,
timeout=aiohttp.ClientTimeout(total=45)
) as response:
if response.status == 200:
data = await response.json()
await self.queue.complete(job.job_id, data)
else:
error = await response.text()
await self.queue.fail(
job.job_id,
f"HTTP {response.status}: {error}"
)
except Exception as e:
await self.queue.fail(job.job_id, str(e))
async def start(self):
"""ワーカープールを開始"""
self._running = True
self.workers = [
asyncio.create_task(self.worker_loop(i))
for i in range(self.num_workers)
]
async def stop(self):
"""ワーカープールを停止"""
self._running = False
await asyncio.gather(*self.workers, return_exceptions=True)
使用例
async def main():
queue = InMemoryJobQueue(max_concurrent=10)
pool = WorkerPool(
queue=queue,
api_key="YOUR_HOLYSHEEP_API_KEY",
num_workers=5
)
# ワーカープール開始
await pool.start()
# 優先度付きで500件投入
print("500件のリクエストを投入中...")
job_ids = []
for i in range(500):
priority = 1 if i % 10 == 0 else 0 # 10%を高優先度に
job_id = queue.enqueue(
prompt=f"ドキュメント {i+1} の分析結果を提供してください",
priority=priority
)
job_ids.append(job_id)
# 結果収集
completed = 0
while completed < 500:
await asyncio.sleep(1)
new_completed = sum(
1 for jid in job_ids
if queue.get_result(jid) is not None
)
if new_completed > completed:
print(f"完了: {new_completed}/500")
completed = new_completed
await pool.stop()
# サマリー
success = sum(
1 for jid in job_ids
if queue.get_result(jid) and
queue.get_result(jid).result
)
print(f"最終結果: 成功 {success}/500")
asyncio.run(main())
手法比較表
| 手法 | 実装難易度 | 最大スループット | コスト効率 | 耐障害性 | レイテンシ | 推奨シーン |
|---|---|---|---|---|---|---|
| リクエストキューイング | ⭐ 低 | 接続数上限 × 1/RTT | ⭐⭐ 普通 | ⭐⭐⭐ 高 | 高(キュー待機あり) | バックグラウンド処理、低優先度タスク |
| リクエストバッチング | ⭐⭐ 中 | 非常に高(50件/呼) | ⭐⭐⭐⭐⭐ 最高(25%割引) | ⭐⭐ 中 | 中〜高(バッチ完了待機) | オフライン処理、大量データ変換 |
| 分散フォールトトレラント | ⭐⭐⭐ 中〜高 | 高(並列キー使用) | ⭐⭐⭐⭐ 高 | ⭐⭐⭐⭐⭐ 最高 | 低〜中 | ミッションクリティカル、本番サービス |
| ワーカープール | ⭐⭐⭐⭐ 高 | 高(動的スケール) | ⭐⭐⭐⭐ 高 | ⭐⭐⭐⭐⭐ 最高 | 低 | 大規模リアルタイム処理 |
HolySheep AI独自の優位性
HolySheep AIは同時接続数制限の突破において、他プロバイダーにない 특異なメリットを提供します:
- 業界最安値の汇率:¥1=$1の固定レートは公式¥7.3=$1比85%節約。これは大口ユーザーにとって年間数十万円のコスト削減になります
- WeChat Pay / Alipay対応:中国企业でも簡単に決済でき、美元ベースの制約がありません
- <50msの低レイテンシ:アジアリージョン最適化により、北米プロバイダー相比劇的に高速
- 登録ボーナス:初回登録で無料クレジットが付与され、本番投入前の検証が気軽に可能
向いている人・向いていない人
✅ 向いている人
- 月間100万トークン以上を消費するヘビーユーザー
- 中国本土またはアジア太平洋地域にいる開発チーム
- 複数プロバイダーのAPIキーを管理したくない人
- 人民元で請求書を処理する必要がある企業
- 低レイテンシが求められるリアルタイムアプリケーション開発者
❌ 向いていない人
- 北米リージョンの专用インフラが必要な場合(法的要件等)
- SLAが99.9%以上必須の超ミッションクリティカル用途
- すでにOptimizedされたマルチプロバイダー構成を持っている場合
価格とROI
2026年output価格の主要モデル比較:
| モデル | 通常価格($/MTok) | HolySheep価格($/MTok) | 節約率 | 月間1万ドルの場合 |
|---|---|---|---|---|
| GPT-4.1 | $60.00 | $8.00 | 87%OFF | $133/月相当 |
| Claude Sonnet 4.5 | $135.00 | $15.00 | 89%OFF | $111/月相当 |
| Gemini 2.5 Flash | $7.50 | $2.50 | 67%OFF | $333/月相当 |
| DeepSeek V3.2 | $1.10 | $0.42 | 62%OFF | $2,381/月相当 |
私の实践经验では、同時接続数制限の突破とHolySheepの組み合わせにより、従来の方法相比で年間500万円以上のコスト削減を実現したプロジェクトもあります。特にバッチ処理を活用するオフライン分析ワークロードでは、元のコスト比80%减達成は珍しくないです。
HolySheepを選ぶ理由
同時接続数制限の解決策としてHolySheep AIを選択すべき理由は明白です:
- 85%のコスト削減:¥1=$1の汇率は他の追随を許さない
- ネイティブ的人民元決済:WeChat Pay/Alipayで気軽にチャージ可能
- <50msの応答速度:アジアからのアクセスに最適
- batch APIの25%割引:大批量処理をさらに効率化
- 無料クレジット付き登録:リスクなく試用可能
複数の同時接続数制限突破手法を組み合わせることも可能ですが、ベースプロバイダーとしてHolySheepを採用すれば、シンプルさとコスト効率を同時に最大化できます。
よくあるエラーと対処法
エラー1:429 Too Many Requests
# 症状:API呼び出し時に429エラーが频発する
原因:同時接続数またはレート制限を超過
対処法:指数バックオフ+リクエスト間隔の制御
import asyncio
import aiohttp
async def call_with_retry(
url: str,
headers: dict,
payload: dict,
max_retries: int = 5,
base_delay: float = 1.0
):
for attempt in range(max_retries):
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as session:
try:
async with session.post(
url, json=payload, headers=headers,
timeout=aiohttp.ClientTimeout(total=30)
) as response:
if response.status == 200:
return await response.json()
elif response.status == 429:
# 指数バックオフ:2^attempt秒待機
delay = base_delay * (2 ** attempt)
print(f"Rate limit hit. Waiting {delay}s...")
await asyncio.sleep(delay)
else:
raise aiohttp.ClientError(f"HTTP {response.status}")
except Exception as e:
if attempt == max_retries - 1:
raise
await asyncio.sleep(base_delay * (2 ** attempt))
raise RuntimeError("Max retries exceeded")
エラー2:Connection Pool Exhausted
# 症状:aiohttp.ClientError: Pool limit reached
原因:TCPConnectorの接続プール上限に達している
対処法:プールサイズの適切な設定+接続の再利用
import a