1秒あたりの通話数(CPS)の上限
概要
すべてのVonage Accountには、1秒あたりの通話数(CPS)の上限が設定されています。これは、1秒単位のローリングウィンドウ内で発信できる新規通話の最大本数を制限するものです。
デフォルトの制限は 3 CPS です。この制限を超えると、プラットフォームは超過分の呼び出しを拒否します。通常、REST API では 429 Too Many Requests レスポンスが、SIP Trunking では SIP 503 Service Unavailable が返されます。
このガイドでは、CPSとは何か、なぜ存在するのか、総通話量が少なくてもバーストがどのように障害を引き起こすのか、そして確実に制限内に収まるようにシステムを設計する方法について解説します。
CPSの上限を引き上げたいですか? ご要望に応じて、限度額を引き上げることが可能です。 Vonageへのお問い合わせ お客様のご要望についてご相談させていただきます。
CPSが存在する理由
CPSはレート制御の仕組みであり、容量制限ではありません。これは、プラットフォームの安定性と、すべてのAccountにわたる公平なリソース配分を確保するためのものです。たとえ同時接続数の上限が高い大規模なAccountであっても、同じ1秒の間に大量の通話を開始すると、下流のシグナリングインフラを飽和させてしまう可能性があります。
バーストがどのように障害を引き起こすか
最もよくある間違いは、平均CPSと瞬時CPSを混同することです。
10秒間に30件の呼び出しを行う必要があるシステムを考えてみましょう(平均3 CPS)。もし、これら30件の呼び出しがすべて同時にトリガーされた場合(例えば、深夜0時にバッチジョブが実行された場合など)、それらはすべて最初の1秒間に到着し、そのうち27件は拒否されてしまいます。
Without throttling (30 calls, all fired at t=0):
t=0s ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ← 30 attempted, 27 rejected
t=1s ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
...
With throttling (30 calls, 3 per second):
t=0s ▓▓▓ ← 3 accepted
t=1s ▓▓▓ ← 3 accepted
t=2s ▓▓▓ ← 3 accepted
...
(all 30 succeed)
この制限は、プラットフォームの端で評価されるものであり、ユーザーが制御するウィンドウ全体で平均化されるわけではありません。クライアント側のスロットリングでは、呼び出しがVonageに到達する前に、このレート制限を確実に適用する必要があります。
一般的なベストプラクティス
これらの原則は、Voice API(VAPI)を使用する場合でも、SIP Trunkingを使用する場合でも、同様に適用されます。
- 制限は、Vonage側ではなく、貴社側で適用してください。 拒否された通話の再試行に頼ってはいけません。大規模な429/503エラーは、それ自体がトラフィックを発生させ、システムのパフォーマンスを低下させます。発信通話は、インフラストラクチャから発信される前に遮断してください。
注: お客様のインフラストラクチャがCPS制限を大幅に超えている場合、Vonageはプラットフォームおよび他の顧客を保護するため、お客様のトラフィックを一時的に遮断することがあります。
-
トークンバケット法またはリーキーバケット法を使用してください。 これらのアルゴリズムは、レート制限を目的として特別に設計されています。トークンバケットは一定のレート(例:1秒あたり3トークン)で補充され、各呼び出しごとに1トークンが消費されます。バケットが空の場合、呼び出しは待機状態になります。ほとんどのプログラミング言語には、これを数行のコードで実装できるライブラリが用意されています。
-
CPSの上限は発信通話にのみ適用されますが、すべての エンドポイントの種類. 着信はCPS制限の対象外です。ただし、発信の制限は、ダイヤル先のエンドポイントの種類にかかわらず一律に適用されます。以下のすべてがCPS予算から差し引かれます:
phone— PSTN番号への発信sip— SIP URI または SIP Trunking への発信websocket— コールレッグとして確立された各アウトバウンド WebSocket 接続は、CPS に対して 1 コールとしてカウントされますapp— Client SDK/WebRTCのアプリ内エンドポイントへの呼び出し
Applicationsで、同じ秒間に複数のエンドポイントタイプが混在する場合(たとえば、電話をかけながら同時にWebSocket接続を開く場合など)、その両方がカウントされます。スロットリングの設計にあたっては、エンドポイントタイプごとにではなく、すべてのエンドポイントタイプを合わせた合計の送信レートを追跡するようにしてください。
-
再試行時にジッターを追加する。 (一時的なネットワークエラーなどにより)再試行を行う場合は、バックオフにランダムなジッター(50~500 ms)を追加してください。ワーカーのプールから同期して再試行を行うと、元のバーストが再現される可能性があります。
-
429/503レスポンスを監視し、アラートを発行する。 ロギングパイプラインにおけるリジェクト率を追跡してください。リジェクト率が急激に上昇した場合は、上流のトラフィックが急増していることを示しています。CPS制限の引き上げを依頼する前に、その原因を調査してください。コール作成時のCPS消費量をリアルタイムで監視するには、
return_cps_on_startedのパラメータPOST /callsリクエスト、またはreturnCpsOnStartedある NCCOconnectアクション.を参照のこと。 Voice API Webhook リファレンス 詳細はこちら。
SIP Trunking:PBX側のCPS設定
Vonage SIP Trunkingを使用する場合、発信元のPBXが発信側のSIP INVITEメッセージを送信します。CPS制限は、通話がVonage SIPゲートウェイに到達する前に、PBX側で適用する必要があります。ほとんどの企業向けPBXプラットフォームには、発信通話のスロットリング機能やトランクグループのペース制御機能が組み込まれています。
重要だ: これらの設定は、アクティブな通話容量ではなく、新規の送信SIPシグナリングのレートを制限するものです。一時的なトラフィックの急増に備えた余裕を持たせるため、VonageのCPS制限値と同等か、それをわずかに下回るように設定してください。
注: 以下の設定例はあくまで参考です。独自の設定を作成する際は、販売元にお問い合わせください。
Asterisk / FreePBX
Asterisk では、発信コールのレート制御は、ダイヤルプランレベルで以下の GROUP_COUNT(${EPOCH}) 現在の秒の間に発信された通話をカウントし、それ以上の通話を待機ループに保持する仕組み:
[globals]
calls_per_sec=3
[OUTBOUND]
exten => _X.,1,Set(GROUP()=${EPOCH})
same => n,GotoIf($[${GROUP_COUNT(${EPOCH})}>${calls_per_sec}]?DELAY,${EXTEN},1)
same => n,Dial(PJSIP/vonage-trunk/${EXTEN})
[DELAY]
exten => _X.,1,Wait(0.5)
same => n,Goto(OUTBOUND,${EXTEN},1)
について call-limit PJSIPエンドポイントのこのオプションは、レートではなく、同時接続可能なチャネルの最大数を制御します。これは上限値として有用ですが、CPS制御としては機能しません。
詳しくは Asterisk の res_pjsip 設定.
3CX
3CXでは、CPSは以下の方法で管理できます。 同時通話 「設定」の下にある 管理 > 音声・チャット > [トランク] > [オプション] タブ、これはトランク経由の同時通話数(着信と発信の合計)の上限を定めるものです。Vonage CPSの上限に対して控えめに設定することで、通話量の急増に対する実用的な予防策となります。なお、これは同時通話容量を制御するものであり、発信レートを制御するものではありません。
詳しくは 3CXのSIP Trunkingオプション.
Cisco Unified Communications Manager (CUCM)
Cisco環境では、CPSスロットリングは、CUCMとVonage SIPゲートウェイの間に配置されるセッションボーダーコントローラであるCisco Unified Border Element(CUBE)によって処理されます。CUBEでは、次のコマンドを使用します。 call-spike threshold そして voice service voip CPSを適用するためのレート制限ディレクティブ。CUCM内では、「ロケーション」が帯域幅に基づいて通話受付制御を行い、これにより同時接続容量が管理されます。
詳しくは Cisco CUBE 設定ガイド.
Avaya Aura / セッションマネージャー
Avaya環境では、CPSの適用はAvaya Session Border Controller for Enterprise(SBCE)によって処理され、SBCEはトランクごとのシグナリングレートポリシーをサポートしています。Avaya Session Managerは、ロケーションおよびSIPエンティティリンクを通じて通話量を管理しており、これらはリンクごとの同時接続容量を制御します。
詳しくは Avaya SBCE ドキュメント.
FreeSWITCH
FreeSWITCH は、 sessions-per-second パラメータの autoload_configs/switch.conf.xml. これにより、システム全体におけるすべての新規コールレッグのレートに上限が設定されます:
<!-- autoload_configs/switch.conf.xml -->
<param name="sessions-per-second" value="3"/>
<param name="max-sessions" value="1000"/>
ゲートウェイごとのCPS制御を行うには、 dialplan limit 特定のリソースに対してレート制限を適用するためのアプリケーション。
詳しくは FreeSWITCH SBCの設定/通話受付制御.
Voice API:発信コールのスロットリング
Voice API を使用して発信を行う場合、アプリケーションが直接、 POST /calls リクエスト。このプラットフォームはHTTPを返します 429 初回にCPSの上限を超えた場合 POST /calls リクエスト。ただし、NCCO 内の connect アクションを介して開始されたその後の呼び出しは非同期で処理されます。これらが CPS 制限を超えた場合、元のリクエストに対して 429 は返されません。その代わりに、 rejected ステータスコールバックは、 detail フィールドを throttled:
{
"from": "442079460000",
"to": "447700900000",
"detail": "throttled, see knowledge article https://api.support.vonage.com/hc/en-us/articles/207100288",
"conversation_uuid": "CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"status": "rejected",
"direction": "outbound",
"timestamp": "2020-01-01T12:00:00.000Z"
}
注: イベントのウェブフックハンドラーが、以下の点を確実に考慮していることを確認してください。 rejected コールバックを throttled 詳細、単なるHTTPだけではない 429 回答。
シンプルなトークンバケット方式によるスループット制御の実装
以下の例は、CPS制限を遵守しつつ、発信コールのバッチをディスパッチする方法を示しています。ここでは、asyncio(Python)を用いた単純なリーキーバケットパターンを採用していますが、これはどの言語においても必要となるロジックの典型例です。
import asyncio
import httpx
import random
import time
VONAGE_API_URL = "https://api.nexmo.com/v1/calls"
CPS_LIMIT = 3 # Match your account's CPS limit
JITTER_MS = 100 # Add up to 100 ms of random jitter per call
async def place_call(client: httpx.AsyncClient, call_payload: dict) -> dict:
response = await client.post(VONAGE_API_URL, json=call_payload)
response.raise_for_status()
return response.json()
async def dispatch_calls(call_payloads: list[dict]):
"""
Dispatch a batch of outbound calls at a controlled rate.
Fires CPS_LIMIT calls per second, with per-call jitter.
"""
interval = 1.0 / CPS_LIMIT # seconds between each call slot
async with httpx.AsyncClient(headers={"Authorization": "Bearer <JWT>"}) as client:
tasks = []
for i, payload in enumerate(call_payloads):
# Sleep until the next call slot, plus random jitter
jitter = random.uniform(0, JITTER_MS / 1000)
await asyncio.sleep((interval if i > 0 else 0) + jitter)
task = asyncio.create_task(place_call(client, payload))
tasks.append(task)
print(f"[{time.strftime('%H:%M:%S')}] Dispatched call {i+1}/{len(call_payloads)}")
results = await asyncio.gather(*tasks, return_exceptions=True)
failures = [r for r in results if isinstance(r, Exception)]
if failures:
print(f"{len(failures)} call(s) failed: {failures}")
return results
# Example usage
if __name__ == "__main__":
calls = [
{
"to": [{"type": "phone", "number": "14155550100"}],
"from": {"type": "phone", "number": "14155550199"},
"ncco": [{"action": "talk", "text": "Hello from Vonage."}]
}
# ...
# repeat for each call
] * 30 # 30 calls total
asyncio.run(dispatch_calls(calls))
要点
interval = 1.0 / CPS_LIMIT3 CPSの場合、約333ミリ秒ごとに正確に1つのコールスロットを確保します。制限値が引き上げられた場合は、これを調整してください。- ジッターにより、マルチプロセス展開におけるすべてのワーカーが、同じミリ秒の境界で実行されることを防ぎます。
asyncio.gatherこれにより、一度ディスパッチされると、すべての呼び出しが同時に実行可能になります。スロットルは開始頻度に対してのみ適用され、実行時間には適用されません。- マルチプロセスシステムや分散システムの場合、トークンバケットは共有する必要があります(例:Luaスクリプトや専用のレート制限サイドカーを用いたRedis経由など)。プロセスごとにバケットを設定すると、複数のワーカーを実行した際にAccount全体の上限を超えてしまうことになります。
429件の回答への対応
async def place_call_with_retry(client, payload, max_retries=3):
for attempt in range(max_retries):
try:
return await place_call(client, payload)
except httpx.HTTPStatusError as e:
if e.response.status_code == 429 and attempt < max_retries - 1:
backoff = (2 ** attempt) + random.uniform(0, 1)
print(f"Rate limited. Retrying in {backoff:.2f}s...")
await asyncio.sleep(backoff)
else:
raise
ワーカー間で同期したリトライの集中を避けるため、固定のスリープ時間ではなく、ジッタ付きの指数関数的なバックオフを使用してください。
Accounts with Subaccounts: Hierarchical CPS Enforcement
このセクションは、VonageのSubaccounts(サブAPIキー)を使用している場合にのみ該当します。統合で単一のメインAPIキーを使用している場合は、このセクションをスキップできます。詳しくは、 Subaccounts API の概要 一般的なSubaccountsの管理のために。
2層モデルの仕組み
CPSは、以下の2つのレベルで同時に実施されます:
- サブアカウントの制限:個々のサブAPIキーには、それぞれ独自のCPS上限が設定されています。そのキーから発信されるトラフィックは、この上限を超えてはなりません。
- メインAPIキーの上限:すべてのキー(メインおよびすべてのサブアカウント)にわたるCPSの合計は、メインAPIキーのCPS設定によって制限されます。これは、Account全体のトラフィックに対する絶対的な上限となります。
両方の制限は同時に適用されます。サブアカウントの制限またはメインキーの上限のいずれかに達した場合、呼び出しは拒否されます。
例
| キー | CPSの個別上限額 |
|---|---|
| メインAPIキー | 20 CPS |
| サブAPIキー 1 | 10 CPS |
| サブAPIキー 2 | 10 CPS |
| サブAPIキー 3 | 10 CPS |
任意の1秒間において、サブキー1は最大10回の呼び出し、サブキー2は最大10回の呼び出し、サブキー3は最大10回の呼び出しを実行できますが、これら3つを合わせた合計(メインキー自体での呼び出しを含む)は、20 CPSを超えてはなりません。 サブアカウントの制限値の合計(30)は関係ありません。常にメインの上限が優先されます。
Main API key cap: 20 CPS
┌─────────────────────────────────────────────┐
│ Sub-key 1 │ Sub-key 2 │ Sub-key 3 │
│ ≤ 10 CPS │ ≤ 10 CPS │ ≤ 10 CPS │
│ │
│ Combined total must stay ≤ 20 CPS │
└─────────────────────────────────────────────┘
これが実際にどういう意味を持つのか
Subaccounts share the parent account's budget. When running multiple workloads or customers on separate subkeys, they compete for the same main key allocation. A traffic spike on one subaccount can cause requests to be rejected on all other subaccounts, even if each individual subaccount is within its own limit.
SIP TrunkingとVAPI通話のいずれも、同じ合計上限枠に算入されます。これらを組み合わせて利用する場合、 SIP INVITE メッセージと POST /calls RESTリクエストはすべて、同じメインキーの制限枠から割り当てられます。同じアカウント階層の下で両方の製品を使用する場合は、それに応じて容量を設計してください。
メインキーの制限値が注目すべき数値です。CPSの引き上げをリクエストする際は、必ずメインAPIキーの制限値を引き上げるようにしてください(メインの制限値がすでに制約条件となっている場合、サブアカウントの制限値のみを引き上げても、メインの制限値を変更しない限り効果はありません)。
Subaccounts CPS向けの設計
- メインキーの上限は、サブアカウントの上限の合計ではなく、ピーク時の総需要に合わせて設定してください。サブアカウントがすべて同時に上限に達することはめったにない場合は、メインの上限をサブアカウントの上限の合計よりも低く設定しても問題ありませんが、最悪のシナリオを想定してモデル化してください。
- サブアカウントの制限値は、意図的に設定してください。各ワークロードから予想されるトラフィックの割合に応じて、サブアカウントごとの制限値を調整してください。サブアカウントの制限値を過大に設定すると、余裕があるという誤った認識を招きます。
- メインキーレベルだけでなく、コード内でサブアカウントごとのスロットリングを適用してください。メインの制限が十分に余裕があっても、スロットリングが適用されていないサブアカウントが不釣り合いな割合のリソースを消費することで、他のサブアカウントのリソースが枯渇してしまう可能性があります。
CPSの上限引き上げの申請
デフォルトの3 CPSという制限は、ほとんどの開発や小規模な本番環境での利用には十分です。大規模なアウトバウンドキャンペーン、コンタクトセンターでの導入、あるいは大規模なPBXシステムにサービスを提供するSIPトランクについては、より高い制限値が利用可能です。 Vonageへのお問い合わせ お客様の利用状況や予想される通話量に基づき、Vonageがご依頼内容を審査し、Accountの制限を引き上げます。通常、1営業日以内に反映されます。