OpenWebUI のパフォーマンス監視と負荷テスト方法
はじめに
目的:ローカルで動かす OpenWebUI(v0.6.5)+自作Mockupバックエンドを対象に、リソース監視と負荷テストのベストプラクティスをまとめたチュートリアル。
対象読者:Docker・Prometheus/Grafana・Apache JMeter をある程度使ったことがある中級者向け。
ソースコード:git上のプロジェクトは下記。mockupは10秒ごとに10回適当な回答をする超軽量llmモックアップ。
https://github.com/notfolder/openwebui-load-test
⚠️注意
モックアップの同時接続律速の可能性があるので、モックアップの同時接続について対応を考える必要あり。
前提環境とバージョン
- OS:macOS 15.5
- OpenWebUI:ghcr.io/open-webui/open-webui:v0.6.5
-
バックエンド:自作Mockup(
OLLAMA_BASE_URL
で接続) - Docker Desktop:v4.42.0
- Prometheus:v2.48.0
- Grafana:v9.5.0
- cAdvisor:v0.49.1
- JMeter:5.6.3
テスト履歴
- 同時200まではエラーなし
- 250で5%エラー。NoHttpResponseException
- nginx.confに下記を追記
worker_processes auto;
events {
worker_connections 10240;
multi_accept on;
}
- 250でエラーなし。パフォーマンスに大きな影響なし
- 500にしても平均応答時間は10.111秒(理論値10秒:sleep(1)で10メッセージ返しているので)
- 1000だと平均13秒、max79秒
- mockをgnicorn化するためDockerfileにした
- 1000でmax12秒,平均10.711秒.問題なし
- 2000でmax20秒,平均15秒
目次
- 構成とリソース監視のセットアップ
- Grafana ダッシュボードの導入
- JMeter を用いた負荷テスト
- まとめ・次のステップ
1. 構成とリソース監視のセットアップ
1.1 リポジトリ構成
openwebui-load-test/
├─ docker-compose.yml
├─ nginx.conf
├─ prometheus.yml
└─ jmeter/
└─ openwebui-test-plan.jmx
1.2 docker-compose.yml(抜粋と注意点)
version: "3.8"
services:
openwebui:
image: ghcr.io/open-webui/open-webui:v0.6.5
ports: ["3000:8080"]
environment:
- OLLAMA_BASE_URL=http://host.docker.internal:11434 # Docker Desktop for Mac の場合
- ENABLE_OPENAI_API_COMPAT=true # API互換モードを有効化
extra_hosts:
- "host.docker.internal:host-gateway" # host.docker.internal の解決
networks: [monitor-net]
nginx:
image: nginx:alpine
ports: ["80:80"]
volumes: ["./nginx.conf:/etc/nginx/nginx.conf:ro"]
depends_on: [openwebui]
networks: [monitor-net]
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
privileged: true
ports: ["8081:8080"]
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
networks: [monitor-net]
prometheus:
image: prom/prometheus
ports: ["9090:9090"]
volumes: ["./prometheus.yml:/etc/prometheus/prometheus.yml"]
networks: [monitor-net]
grafana:
image: grafana/grafana
ports: ["3001:3000"]
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
networks: [monitor-net]
networks:
monitor-net:
driver: bridge
docker-compose.ymlでの注意点
-
extra_hosts
: macOS Docker Desktopではhost.docker.internal
を指定し、バックエンドMockupへの接続を確保 -
version: "3.8"
警告: Docker Compose v2以降はversion
属性が非推奨。docker compose
利用時は省略可
1.3 nginx.conf(SSE/WebSocket対応)
events {}
http {
server {
listen 80;
location / {
proxy_pass http://openwebui:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# SSE・WebSocket 用ヘッダー
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# ストリーミングを途切れさせない設定
proxy_buffering off;
proxy_cache off;
proxy_set_header Accept-Encoding "";
chunked_transfer_encoding off;
}
location /nginx_status {
stub_status;
allow all;
}
}
}
nginx.confでの引っかかった点
-
Upgrade
/Connection
: ストリーミング応答を扱う際に必要。未設定だとクライアント側でJSONパースエラーが発生 -
proxy_buffering off
: イベントストリームがバッファリングされて遅延する問題の回避
1.4 prometheus.yml(Exporter 指定の注意)
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'nginx'
static_configs:
- targets: ['nginx-exporter:9113']
prometheus.ymlでのポイント
-
nginx-exporter
: Nginxの同時接続数を取得するにはnginx-prometheus-exporter
を/nginx_status
経由でスクレイプ -
ネットワーク名不一致: Docker Compose v2では
monitor-net
がプロジェクト名付きのネットワーク名になる場合があるため、docker network ls
で実際の名前を確認
2. Grafana ダッシュボードの導入
- 推奨テンプレート:ID 13496 “Docker and system monitoring”
インポート手順:
- Grafana → + > Import
- ID
13496
を入力 → Load - Prometheus を選択 → Import
表示項目:
- ホスト Load Average, ディスク使用率
- コンテナ別 CPU/メモリ/ネットワーク I/O
- Nginx Active connections (stub_status)
3. JMeter を用いた負荷テスト
3.1 テストプラン概要
- 同時ユーザー:10
- Ramp-up:5秒
- ループ:5回
-
エンドポイント:
POST http://localhost:3000/api/chat/completions
-
ヘッダー:
Content-Type: application/json
3.2 jmeter/openwebui-test-plan.jmx(抜粋)
<ThreadGroup num_threads="10" ramp_time="5" loops="5">…</ThreadGroup>
<HTTPSamplerProxy testname="Chat Completion" method="POST" domain="localhost" port="3000" path="/api/chat/completions">
<stringProp name="HTTPSampler.postBodyRaw">true</stringProp>
<stringProp name="Argument.value">{
"model":"dummy:latest",
"messages":[{"role":"user","content":"こんにちは"}]
}</stringProp>
</HTTPSamplerProxy>
3.3 実行コマンド
jmeter -n -t jmeter/openwebui-test-plan.jmx -l results.jtl
4. まとめ・次のステップ
-
今回の内容: Docker Compose + Nginx + cAdvisor + Prometheus + Grafana + JMeter による監視&負荷テスト
-
次のステップ:
- 本番環境向け API Gateway 設定
- 実サービスモデルへの切り替え
- アラート設定と運用フロー構築
タグ: #Docker
#OpenWebUI
#Prometheus
#Grafana
#JMeter
#負荷テスト
5. この記事の作成過程