負載測試你的 Databricks Apps 代理程式

負載測試會找出 Databricks Apps 代理在效能下降前能承受的最大每秒查詢次數(QPS)。 本頁會展示如何完成以下操作:

  1. 部署一個模擬版本的代理程式,以隔離基礎設施吞吐量與 LLM 延遲。
  2. 用 Locust做一個漸進到飽和的負載測試。
  3. 透過互動式儀表板分析結果。

你可以利用 Claude Code 技能跟隨 AI 輔助路徑,或手動設定每個步驟。

負載測試儀表板的動畫預覽,顯示各計算配置的 QPS、延遲與 RAMP 進展圖表。

Requirements

  • 一個Azure Databricks工作區,啟用了 Databricks 應用程式。
  • 一個已部署(或準備部署)於 Databricks 應用程式上的代理應用程式,使用 OpenAI 代理 SDK、LangGraph 或自訂框架。 請參閱 使用舊版代理伺服器在 Databricks 應用程式上執行代理程式。
  • Databricks CLI 已安裝並驗證。 請參閱安裝或更新 Databricks CLI。
  • Python 3.10+ 搭配 uv 套件管理器。
  • (針對 AI 輔助路徑)已安裝 Claude 程式碼 。
  • (大約 1 小時以上的負載測試)擁有 M2M OAuth 憑證(client_id 和 client_secret)的服務主體。 請參見 使用 OAuth 授權服務主體存取至 Azure Databricks。
    • 對於短時間負載測試(少於 ~1 小時),你現有的使用者(U2M)OAuth 憑證 databricks auth login 運作正常。 若測試較長,請使用 M2M OAuth 搭配服務主體——U2M 令牌在長程執行中會過期,導致測試中途失敗。 建立服務主體需要工作區管理員權限。

如果你用 Claude Code,這項技能 /load-testing 會自動化工作流程。 它會讀取你的代理程式碼、產生模擬程式碼、建立負載測試腳本,並引導你完成部署流程。

Tip

請讓 Claude Code 來為你完成:

Clone https://github.com/databricks/app-templates and run the /load-testing skill against the {your-template} template.

或者按照以下步驟操作。

步驟 1:複製代理範本

這項技能 /load-testing 包含在 databricks/app-templates 的資料庫中,既是頂層 agent-load-testing 技能,也已預先同步到每個個別代理範本中。 如果你已經有來自app-templates的專案,那麼你已經有這項技能了。

複製倉庫並切換到要進行負載測試的代理程式模板目錄:

git clone https://github.com/databricks/app-templates.git
cd app-templates/{your-template}

步驟二:執行負載測試技能

在 Claude Code 中,執行:

/load-testing

這個技能會互動式地引導你完成以下步驟。 你可以跳過模擬測試來直接測試代理,或者如果應用程式已在執行,則可以跳過部署。

  1. 收集參數:詢問你的部署狀態、運算大小、工作者配置及 OAuth 憑證。
  2. 建立載入測試腳本:產生 、 locustfile.py 和 run_load_test.py,針對你的專案量身打造。
  3. 模擬你的 LLM:建立一個針對你的 SDK(OpenAI Agents SDK、LangGraph 或自訂)的模擬客戶端,用可設定的串流延遲取代真實的 LLM 呼叫。
  4. 部署測試應用程式:引導你部署多個不同計算大小與工作者數量的應用程式配置。
  5. 執行測試:使用 M2M OAuth 認證及 ramp-to-saturation 執行負載測試。
  6. 產生結果:產生一個互動式 HTML 儀表板,包含 QPS、延遲與失敗指標。

手動設定

請依照以下步驟設定並執行負載測試,無需 AI 協助即可。

步驟 1:模擬你代理人的 LLM 呼叫(可選)

如果你想要包含真實 LLM 延遲的端到端結果,可以跳過這一步。 要單獨衡量 Databricks Apps 的基礎設施吞吐量,可以模擬 LLM,避免其每次請求延遲(通常 1-30 秒)成為瓶頸。

模擬會回傳帶有可設定串流延遲的預設回應,保留完整的請求/回應流程(SSE 串流、工具派遣、SDK 執行器),只替換 LLM。 這能顯示 Databricks Apps 平台能提供的最高 QPS,並避免在負載測試時產生 Foundation Model API 令牌成本。

模擬時間由兩個環境變數控制:

變數 Default 描述
MOCK_CHUNK_DELAY_MS 10 串流文字區塊之間的毫秒延遲
MOCK_CHUNK_COUNT 80 每個回應的文字區塊數量

預設情況下,每個模擬回應約需 800 毫秒(10 毫秒 x 80 區塊),明顯快於真實的 LLM 回應(3-15 秒)。 吞吐量數字反映的是平台,而非模型。

建立一個模擬客戶端,取代真正的大型語言模型客戶端。 其餘的代理程式碼保持不變,而方法則取決於你的 SDK。 關於 OpenAI,請參見 mock_openai_client.py 的參考實作databricks/app-templates。 同樣的模式也會適用於其他 SDK。

OpenAI 智能代理 SDK

Create agent_server/mock_openai_client.py — 實作MockAsyncOpenAI並包含串流的chat.completions.create()類別。 它會即時回傳工具呼叫區塊(模擬大型語言模型決定呼叫工具的過程),而文字回應區塊的延遲則可透過 MOCK_CHUNK_DELAY_MS 和 MOCK_CHUNK_COUNT 環境變數進行設定。

將它替換到你的代理中:

from agent_server.mock_openai_client import MockAsyncOpenAI
from agents import set_default_openai_client, set_default_openai_api

set_default_openai_client(MockAsyncOpenAI())
set_default_openai_api("chat_completions")

其餘的代理程式碼(處理器、工具、串流邏輯)保持不變。

LangGraph

將 ChatDatabricks 模型替換為一個回傳預先建構 AIMessage 物件的模擬:

# Before:
# model = ChatDatabricks(endpoint="databricks-claude-sonnet-4-6")

# After:
from agent_server.mock_llm import MockChatModel
model = MockChatModel()

模擬應在第一次呼叫時回傳帶有工具呼叫的物件,後續呼叫時回傳 AIMessage 文字內容,並可設定串流延遲。

海關代理

將代理程式所進行的任何外部 API 呼叫(LLM、AI 搜尋、工具 API)都以模擬實作包裝,使其回傳逼真的回應格式,並支援可設定的延遲。

步驟 2:設定負載測試腳本

在你的專案中建立一個 load-test-scripts/ 目錄。 負載測試框架由三個與框架無關的腳本組成,且可與任何 Databricks Apps 代理程式搭配使用。

<project-root>/
  agent_server/                  # Your existing agent code
  load-test-scripts/             # Load testing scripts (create this)
    run_load_test.py             #   CLI orchestrator
    locustfile.py                #   Locust test with SSE streaming + TTFT tracking
    dashboard_template.py        #   Interactive HTML dashboard generator
  load-test-runs/                # Results (auto-created per run)
    <run-name>/
      dashboard.html             #   Interactive dashboard
      test_config.json           #   Test parameters for reproducibility
      <label>/                   #   Per-config Locust CSV output

框架包含以下檔案:

  • locustfile.py:Locust 負載測試發送POST /invocations請求,並使用stream: true解析 SSE 串流,將第一個令牌的時間(TTFT)記錄為自訂指標,使用支持自動刷新功能的 M2M OAuth 令牌交換,實施StepRampShape算法,在每個等級維持step_size秒,同時將使用者數量從 max_users 增至 step_duration。
  • run_load_test.py:一個 CLI 編排器,依序測試每個應用程式 URL,並在每個配置下提供獨立的指標。 它處理 OAuth 代幣刷新,每次測試前會執行健康檢查和預熱,並將結果儲存到 load-test-runs/<run-name>/<label>/。
  • dashboard_template.py:利用 Chart.js 產生獨立的 HTML 儀表板,包含 KPI 卡、條狀圖(QPS、延遲、配置下的 TTFT)、QPS 坡度進度線圖及完整結果表。 可獨立執行: uv run dashboard_template.py ../load-test-runs/<run-name>/。

安裝依賴項

負載測試腳本會在 pyproject.toml 中使用它們自己的 load-test-scripts/,以避免污染代理的生產依賴。 創建 load-test-scripts/pyproject.toml:

[project]
name = "load-test-scripts"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
  "locust>=2.32,<2.40",
  "urllib3<2.3",
  "requests",
]

Note

插腳 locust 到 <2.40。 較新版本>=2.43已知的RecursionError會破壞長負載測試。

請從 load-test-scripts/ 目錄中安裝:

cd load-test-scripts/
uv sync

步驟 3:部署具有不同配置的測試應用程式

部署多個 Databricks 應用程式,分別擁有不同的運算大小和工作者數量,以找到最適合你工作負載的最佳配置。

以下配置聚焦於先前測試中識別出的最佳點。 如果你想要更廣泛的覆蓋範圍,可以在兩側各加一個設定(例如, medium-w1 或 large-w12),但通常下面六個配置就足夠了。

計算大小 工人 建議應用程式名稱
Medium 2 <your-app>-medium-w2
Medium 3 <your-app>-medium-w3
Medium 4 <your-app>-medium-w4
大型 6 <your-app>-large-w6
大型 8 <your-app>-large-w8
大型 10 <your-app>-large-w10

設定計算大小

在建立或更新應用程式時,使用 Databricks CLI 設定運算大小:

# Create a new app with Medium compute
databricks apps create <app-name> --compute-size MEDIUM

# Update an existing app to Large compute
databricks apps update <app-name> --compute-size LARGE

用宣告式自動化套件來設定工作者數量

start-server (透過 AgentServer.run())直接接受 --workers 標誌。 使用 DAB 變數將工作者計數傳入 command 陣列:

variables:
  app_name:
    default: 'my-agent-medium-w2'
  workers:
    default: '2'

resources:
  apps:
    load_test_app:
      name: ${var.app_name}
      source_code_path: .
      config:
        command: ['uv', 'run', 'start-server', '--workers', '${var.workers}']
        env:
          - name: MOCK_CHUNK_DELAY_MS
            value: '10'
          - name: MOCK_CHUNK_COUNT
            value: '80'

targets:
  medium-w2:
    default: true
    variables:
      app_name: 'my-agent-medium-w2'
      workers: '2'
  large-w8:
    variables:
      app_name: 'my-agent-large-w8'
      workers: '8'

部署與驗證

部署每個目標時,請使用 Databricks CLI:

databricks bundle deploy --target medium-w2
databricks bundle run load_test_app --target medium-w2

在執行負載測試前,先確認應用程式是否已啟用:

databricks apps get <app-name> --output json | jq '{app_status, compute_status, url}'

Note

等所有應用程式都達到 ACTIVE 狀態後再繼續。 還在啟動的應用程式會產生誤導性的結果。

步驟四:執行負載測試

設定認證

根據你的執行時間長短選擇驗證方式:

  • 簡短測試(少於 ~1 小時):使用你現有的使用者憑證。databricks auth login 不需要額外設定。
  • 長時間測試(超過~1小時,例如夜間運行):使用M2M OAuth搭配服務主體。 U2M 代幣會在測試中途過期並中斷您的測試執行。 建立服務主體需要工作區管理員權限。

對於 M2M OAuth,執行測試前先匯出服務主體憑證:

export DATABRICKS_HOST=https://your-workspace.cloud.databricks.com
export DATABRICKS_CLIENT_ID=<your-client-id>
export DATABRICKS_CLIENT_SECRET=<your-client-secret>

參數參考

參數 Required Default 描述
--app-url Yes — 應用程式網址測試(可重複使用)
--client-id 長時間的測試 DATABRICKS_CLIENT_ID 環境 服務主體識別碼(M2M OAuth)
--client-secret 長時間的測試 DATABRICKS_CLIENT_SECRET 環境 服務主體客戶端密鑰 (M2M OAuth)
--label No 由網址自動導出 每個應用程式的人類可讀標籤(可重複)
--compute-size No 自動偵測或 medium 每個應用程式的計算尺寸標籤: medium, large(可重複)
--max-users No 300 最大同時虛擬用戶
--step-size No 20 每個增長步驟新增的使用者
--step-duration No 30 每階梯的秒數
--spawn-rate No 20 使用者生成率(使用者/秒數)
--run-name No <timestamp> 本次運行名稱 — 結果已儲存至 load-test-runs/<run-name>/
--dashboard No 關閉 測試完成後產生互動式 HTML 儀表板

範例指令

快速單一應用程式測試(短程——使用你的 databricks auth login 會話):

cd load-test-scripts/

uv run run_load_test.py \
    --app-url https://my-app.aws.databricksapps.com \
    --dashboard --run-name quick-test

完整矩陣涵蓋推薦的6種配置(長期使用——通過M2M認證)。 與--compute-size相同的順序傳遞--app-url旗標:

uv run run_load_test.py \
    --app-url https://my-app-medium-w2.aws.databricksapps.com \
    --app-url https://my-app-medium-w3.aws.databricksapps.com \
    --app-url https://my-app-medium-w4.aws.databricksapps.com \
    --app-url https://my-app-large-w6.aws.databricksapps.com \
    --app-url https://my-app-large-w8.aws.databricksapps.com \
    --app-url https://my-app-large-w10.aws.databricksapps.com \
    --compute-size medium --compute-size medium --compute-size medium \
    --compute-size large --compute-size large --compute-size large \
    --client-id $DATABRICKS_CLIENT_ID \
    --client-secret $DATABRICKS_CLIENT_SECRET \
    --dashboard --run-name overnight-sweep

多次跑動以求統計一致性:

for RUN in r1 r2 r3 r4 r5; do
  uv run run_load_test.py \
      --app-url https://my-app.aws.databricksapps.com \
      --client-id $DATABRICKS_CLIENT_ID \
      --client-secret $DATABRICKS_CLIENT_SECRET \
      --max-users 1000 --step-size 20 --step-duration 10 \
      --run-name my_test_${RUN} --dashboard || break
done

執行過程中會發生什麼事

  1. 健康檢查:驗證應用程式的串流是否正確(能夠接收[DONE])。
  2. 預熱:依序發送請求來預熱應用程式。
  3. 「達到飽和」:每秒增加同時在線用戶。
  4. 飽和偵測:當 QPS 在增加更多用戶後仍達到瓶頸時,就已經達到吞吐量上限。

預估的持續時間

每個被測的應用程式都會經過自己的斜坡,因此總執行時間會隨著矩陣中的配置數量而調整。 請使用以下公式規劃你的跑步時間。

每個應用程式的持續時間: (max_users / step_size) * step_duration 秒。

預設值為 :--max-users 300 --step-size 20 --step-duration 30

  • 15 步 x 30 秒 = 每個應用程式約 7.5 分鐘
  • 建議的6組組態矩陣:每次執行約45分鐘

步驟 5:檢視和解譯結果

  1. 打開儀表板:

    open load-test-runs/<run-name>/dashboard.html
    
  2. (可選)例如,從現有資料重新建立儀表板,例如在更新範本後:

    cd load-test-scripts/
    uv run dashboard_template.py ../load-test-runs/<run-name>/
    

儀表板區段

互動式儀表板包含:

  • KPI 卡:最佳配置(依峰值成功 QPS)、整體峰值 QPS、最低延遲及服務的總請求數。
  • 按配置分類的 QPS:分組條狀圖,顯示中位數 QPS、不含故障的峰值 QPS,以及各配置下的峰值 QPS 並列比較。
  • 依設定延遲:分組顯示 p50 和 p95 延遲的條狀圖。
  • TTFT 根據配置:第一字節時間(p50 和 p95)。
  • 完成的總請求數:每個配置的請求次數。
  • QPS Ramp Progression:折線圖,並標示 QPS、QPS(不包括失敗)、延遲與故障。 包含用於調整最大使用者數量的滑桿,可放大至較低的並發數範圍。 圖表依計算大小分組(中型與大型並列)。
  • 完整結果表:所有有峰值 QPS、峰值使用者、延遲百分位數及故障率的配置。
  • 測試參數:配置摘要以提升重現性。

如何解讀結果

  • 峰值QPS:在任何斜坡階級達到的最大QPS。 這就是該配置的吞吐量上限。
  • 高峰用戶數:達到高峰 QPS 時的同時在線用戶數。 在此點之後增加更多使用者並不會提升吞吐量。
  • 失敗率:應為0% 或非常低。 高失敗率代表應用程式在該並發層級已經過載。
  • QPS 坡度圖:尋找線條變平的地方。 這就是飽和點:增加更多用戶不會提升吞吐量。

基於合成資料的基準測試執行

本節報告內部 Azure Databricks 基準測試與合成代理應用程式的測量結果,該測試中每個 LLM 呼叫都被模擬。 這是與對你自己的代理程式進行負載測試分開的另一項練習:用它來了解你可以預期的結果大致樣貌,並作為容量規劃的粗略起點。

這次跑映展現了什麼

  • 建議起始點:2 名 Medium 運算,或 8 名 Large 運算。
  • 更多員工不一定更好。 在中等難度下,2 名工人(155.1 QPS)以 ~33%擊敗 4 名工人(116.5 QPS)。 模擬工作負載受 CPU 限制,因此一旦超過 2 個工作程序,就會出現 CPU/記憶體爭用,進而抵銷額外的平行化效益。 一個真正受 IO 綁定且主要待在模型端點的代理,可能比這個模擬更可擴展,所以務必測試你自己的代理。
  • 運算規模:大型運算量約為中型運算的 2.2 倍(278.0 對平均 123.5 個峰值 QPS)。
  • 延遲:Large 約比 Medium 低 20%(p50 約為 906 毫秒,相較於 Medium 的 1,180 毫秒),而 TTFT 在 Large 上約為 1,100 毫秒,Medium 則為 1,720–1,820 毫秒。
  • 可靠性:即使有 1,000 名同時使用者,故障率仍維持在 0 或接近 0%。

由於 LLM 為模擬方式處理(串流以固定的每區塊延遲進行模擬),因此這些數據反映的是基礎設施吞吐量,而非端對端代理系統的指標。 它們衡量的是 Databricks 應用程式 FastAPI AgentServer 能平行處理多少請求,而非真實模型的延遲。 呼叫即時大型語言模型端點的生產環境代理程式,QPS 較低且延遲較高,主要由模型回應時間主導。 你自己的數字會隨著代理的複雜度、有效載荷大小、工具呼叫、區域以及你所呼叫的模型端點而有所不同。 為了準確評估容量,請針對您自己的代理程式執行負載測試。

以下表格結果顯示了各組態的完整細分。

測試條件

  • 基準執行:針對 8 種應用程式組態(4 個中型運算、4 個大型運算)各進行 5 個相同的輪次,且每種組態的 uvicorn 工作程序數皆不同。
  • Ramp:同時支援 20 至 1,000 名同時使用者,分 20 名用戶每段等待 10 秒(每次配置 50 步)。
  • 模擬代理:每次請求會串流傳回約 95 個區塊,模擬 LLM token 串流。
  • 總請求量:所有跑線合計約 146 萬件。

按配置分類的峰值 QPS

峰值 QPS 為 5 次執行結果的平均值。

計算大小 工人 平均峰值 QPS 峰值分布範圍 失敗率
Medium 2 155.1 137.0-166.6 0.0%
Medium 4 116.5 112.6-121.8 0.1%
Medium 6 111.9 102.6-117.5 0.0%
Medium 8 110.3 108.3-112.1 0.0%
大型 6 281.6 268.2-292.4 0.0%
大型 8 268.2 265.8-271.0 0.0%
大型 10 288.1 280.3-299.4 0.0%
大型 12 274.2 269.4-278.8 0.0%

按運算規模平均:

計算大小 平均峰值 QPS 平均QPS
Medium 123.5 45.5
大型 278.0 100.1

在這次運算中,大型運算的吞吐量約為中型運算的 2.2 倍。

Troubleshooting

Issue Solution
認證令牌在測試中途過期 對於超過 ~ 1 小時的測試,請從 U2M 切換到 M2M OAuth,並傳遞 --client-id 和 --client-secret
健康檢查失敗 確認應用程式是否啟用: databricks apps get <name> --output json
0 QPS 或無結果 檢查 load-test-runs/<run-name>/<label>/locust_output.log 中的錯誤
儘管用戶數量眾多,QPS 卻偏低 這個應用程式已經飽和了。 試試更多工人或更大運算能力。
高故障率 應用程式已經過載了。 減少 --max-users 或增加工作者/運算能力。
儀表板顯示沒有斜坡資料 Verify results_stats_history.csv 存在於每個結果子目錄中

其他資源

  • 用真實的 LLM 呼叫來測試:跳過模擬步驟,直接部署你的實體代理,來測量端到端延遲,包括 LLM 回應時間。
  • 調整工作者數量:利用測試矩陣結果來找出您計算資源的最佳工作者數。
  • 教學:評估並改進代理 ,以衡量準確性、相關性與安全性,同時衡量吞吐量。
  • 如需了解完整的正式上線準備流程(包括 AI Gateway),請參閱讓你的 Databricks Apps 代理程式做好正式上線準備。