跳至主要內容

延遲額外負擔疑難排解

當您看到 LiteLLM proxy 與 LLM 提供者之間有非預期的延遲額外負擔時,請使用本指南。

看不見的延遲落差​

LiteLLM 會從其處理常式開始執行時開始計算延遲。如果請求在 uvicorn 的事件迴圈中於 處理常式執行之前 等待,這段等待對 LiteLLM 自己的記錄來說是看不見的。

T=0   Request arrives at load balancer
[queue wait — LiteLLM never logs this]
T=10 LiteLLM handler starts → timer begins
T=20 Response sent

LiteLLM logs: 10s User experiences: 20s

要量測處理常式前的等待時間,請在每個 pod 上輪詢 /health/backlog:

curl http://localhost:4000/health/backlog \
-H "Authorization: Bearer sk-..."
# {"in_flight_requests": 47}

或者從 litellm_in_flight_requests Prometheus gauge 抓取 /metrics。

in_flight_requestsALB TargetResponseTime診斷
高高pod 過載 → 擴充
低高延遲發生在 ASGI 之前 — 檢查同步阻塞程式碼或事件迴圈飽和
高正常pod 忙碌但健康,沒有佇列累積

如果您使用的是 AWS ALB,請將 litellm_in_flight_requests 的尖峰與 ALB 的 TargetResponseTime CloudWatch 指標進行關聯。ALB 回報的數值與 LiteLLM 記錄的數值之間的落差,就是看不見的等待時間。

快速檢查清單​

  1. 透過 /health/backlog 或 litellm_in_flight_requests Prometheus gauge 檢查每個 pod 上的 in_flight_requests。這能告訴您請求是否在 LiteLLM 開始處理之前就已排隊。若有無法解釋的延遲,請先從這裡開始。
  2. 收集 x-litellm-overhead-duration-ms 回應標頭 —— 這會告訴您 LiteLLM 在每次請求上的總額外耗時。
  3. 有啟用 DEBUG 記錄嗎? 這是大 payload 造成延遲的首要原因。
  4. 您是否在傳送大型 base64 payload?(圖片、PDF)。請參見 大型 Payload 額外耗時。
  5. 啟用詳細 timing 標頭,以找出時間花在哪裡。

診斷標頭​

x-litellm-overhead-duration-ms(一律啟用)​

LiteLLM 的每個回應都會包含此標頭。它會顯示 LiteLLM proxy 所增加的總延遲額外負擔(毫秒),也就是總回應時間減去 LLM API 呼叫時間。請在每個請求上收集此資訊,以了解您的基準額外負擔。

curl -s -D - http://localhost:4000/v1/chat/completions \
-H "Authorization: Bearer sk-..." \
-d '{"model": "gpt-5.6-terra", "messages": [{"role": "user", "content": "hi"}]}' \
2>&1 | grep x-litellm-overhead-duration-ms

x-litellm-callback-duration-ms(一律啟用)​

顯示建立 callback/記錄酬載所花費的時間(ms)。如果這個值很高(>100ms),您的酬載可能過大,不利於有效率地記錄。

curl -s -D - http://localhost:4000/v1/chat/completions \
-H "Authorization: Bearer sk-..." \
-d '{"model": "gpt-5.6-terra", "messages": [{"role": "user", "content": "hi"}]}' \
2>&1 | grep x-litellm

詳細時間分解(可選啟用)​

設定 LITELLM_DETAILED_TIMING=true 以在回應標頭中取得各階段的時間:

標頭衡量內容
x-litellm-timing-pre-processing-ms驗證、路由、請求處理(LLM 呼叫前)
x-litellm-timing-llm-api-ms實際 LLM API 呼叫持續時間
x-litellm-timing-post-processing-ms回應處理(LLM 返回後)
x-litellm-timing-message-copy-ms記錄層中的訊息複製時間
# Enable detailed timing
export LITELLM_DETAILED_TIMING=true

大型酬載額外負擔​

當傳送大型酬載(>1MB,例如 base64 編碼的圖片/PDF)時,會有三件事可能增加額外負擔:

1. DEBUG 記錄(最常見)​

當啟用 LITELLM_LOG=DEBUG 或 set_verbose=True 時,每個請求酬載都會以 json.dumps(indent=4) 同步序列化。對於 2MB 以上的酬載,單這一步就可能花費 2-5 秒。

修正方式: 請勿在正式環境使用 DEBUG 記錄。改用 INFO 等級:

export LITELLM_LOG=INFO

如果您需要 DEBUG 記錄但有大型酬載,可以提高完整酬載記錄的大小閾值:

# Only fully serialize payloads under 100KB for DEBUG logs (default)
export MAX_PAYLOAD_SIZE_FOR_DEBUG_LOG=102400

2. 記錄酬載中的 Base64​

callback 酬載(傳送到 Langfuse 等)包含訊息內容。大型 base64 字串會在記錄酬載中自動截斷為大小佔位符。

您可以控制截斷閾值:

# Max base64 characters before truncation (default: 64)
export MAX_BASE64_LENGTH_FOR_LOGGING=64

3. stdout 記錄中的 Base64 與過長行​

提供者錯誤可能會回顯整個請求,而在 DEBUG 等級下,請求 payload 本身也會被列印,因此一個多 MB 的上傳可能會變成需要數秒來格式化與清理的記錄行,並且是在 event loop 內聯完成。兩個上限會限制輸出到 stdout 的內容。這兩者都不會改變 logging callback 接收到的內容。

MAX_BASE64_LENGTH_STDOUT_LOG(預設 4096)會在所有記錄等級與 traceback 中,將任何超過該長度的 base64 片段折疊為像 [base64_data truncated: 2.86MB] 之類的占位符,並保留其前後文字。MAX_STRING_LENGTH_STDOUT_LOG(預設 4096)會在 INFO 及以上等級將整行長度設上限,保留 litellm_truncated skipped N chars 標記前後的開頭與結尾;DEBUG 行則保留完整長度,因此 --detailed_debug 仍會顯示全部內容。將任一項設為 0 即可關閉。

# Collapse base64 runs longer than this in stdout log lines (default: 4096, 0 disables)
export MAX_BASE64_LENGTH_STDOUT_LOG=4096
# Cap INFO and higher stdout log lines at this many chars (default: 4096, 0 disables)
export MAX_STRING_LENGTH_STDOUT_LOG=4096

環境變數參考​

變數預設值說明
LITELLM_DETAILED_TIMINGfalse啟用每個階段的 timing 標頭
MAX_PAYLOAD_SIZE_FOR_DEBUG_LOG102400完整 DEBUG 序列化的最大 payload 位元組數
MAX_BASE64_LENGTH_FOR_LOGGING64記錄中在截斷前允許的 base64 最大字元數
MAX_BASE64_LENGTH_STDOUT_LOG4096stdout 記錄行中的 base64 最大字元數,超過後該段會折疊為大小占位符
MAX_STRING_LENGTH_STDOUT_LOG4096每行 INFO 以上 stdout 記錄的最大字元數,超過後中間會被截斷