跳到主要内容

优化、性能与内存占用

本指南为您提供了优化 Open WebUI 的全面策略。最理想的配置很大程度上取决于您的特定部署目标。请对照以下场景,看看哪一种最符合您的需求:

  1. 弱硬件上的极度隐私(例如树莓派)

    • 目标:将所有内容保留在本地;使资源占用降至最低。
    • 折中方案:您必须使用轻量级的本地模型(SentenceTransformers)并禁用高负载功能,以防止系统崩溃。
  2. 单用户的极高体验质量(例如个人电脑)

    • 目标:在保持高速度和高质量的同时,获得最佳的交互体验。
    • 策略:利用外部 API(如 OpenAI/Anthropic)进行向量嵌入(embeddings)和任务模型计算,以减轻您本地机器的计算负担。
  3. 服务于大量用户的大规模部署(例如企业/生产环境)

    • 目标:高稳定性和高并发能力。
    • 策略:需要配备专用的向量数据库(Milvus/Qdrant)、增加线程池大小、使用缓存来应对负载,并且必须使用 PostgreSQL 代替 SQLite。

⚡ 性能调优(速度与响应)

如果 Open WebUI 运行缓慢或响应迟钝,特别是在生成对话或高并发期间,针对性的优化可以显著改善用户体验。

1. 专用的任务模型

默认情况下,Open WebUI 会自动处理一些后台任务,例如对话标题生成、标签提取和输入自动补全。这些任务在后台运行,如果与主对话模型共享相同的资源,可能会拖慢主模型的生成速度。

建议:为这些后台任务使用运行速度极快、体积小且成本低廉的非推理(NON-REASONING)模型。避免使用大型推理模型(如 o1、r1 或 Claude),因为它们对于简单的后台任务而言过于缓慢且成本高昂。

配置方法:Admin Panel(管理员面板) > Settings(设置) > Interface(界面) 中有两个独立的设置项。系统会根据您当前正在对话的模型,智能地选择使用哪一个:

  • Task Model (External):当您正在与外部模型(如 OpenAI)对话时使用。
  • Task Model (Local):当您正在与本地托管的模型(如 Ollama)对话时使用。

2025 年最佳选择推荐:

  • 外部/云端gpt-5-nanogemini-2.5-flash-litellama-3.1-8b-instant(通过 OpenAI/Google/Groq/OpenRouter 接入)。
  • 本地qwen3:1bgemma3:1bllama3.2:3b

2. 缓存与延迟优化

通过配置以下设置可以有效降低延迟并减少对外部 API 的请求次数。

模型缓存

大幅缩短启动时间并减少对外部服务商的 API 调用。

针对 OpenRouter 和多模型提供商的重要提示

如果您正在使用 OpenRouter 或任何提供成百上千个模型的服务商,强烈建议启用模型缓存。如果不启用缓存,初始页面加载可能会耗费 10 到 15 秒以上的时间,因为应用程序必须查询所有可用的模型。启用缓存可使此过程缩短至几乎瞬间完成。

  • Admin PanelSettings > Connections > Cache Base Model List

  • 环境变量ENABLE_BASE_MODELS_CACHE=True

    • 说明:将模型列表缓存在内存中。仅在应用重启或在 Connections 设置中点击 Save 时才会刷新。
  • 环境变量MODELS_CACHE_TTL=300

    • 说明:为外部 API 响应设置 5 分钟的缓存。

搜索查询缓存

在同一个对话轮次中,复用由 LLM 生成的网页搜索查询来进行 RAG 检索。这可以防止多个检索功能作用于同一个用户提示词时,产生冗余的 LLM 调用。

  • 环境变量ENABLE_QUERIES_CACHE=True
    • 说明:如果启用,相同的搜索查询将被复用于 RAG,而无需为 RAG 生成新的查询,从而节省推理成本和 API 调用次数,进而提升性能。

KV 缓存优化(RAG 性能)

当在大型文档或知识库中进行对话时,能大幅提升后续追问的响应速度。

  • 环境变量RAG_SYSTEM_CONTEXT=True
  • 效果:将 RAG 检索到的上下文注入到**系统消息(system message)**中,而非用户消息(user message)中。
  • 原理:许多 LLM 引擎(如 Ollama、llama.cpp、vLLM)和云服务商(OpenAI、Vertex AI)都支持 KV 前缀缓存(prefix caching)提示词缓存(Prompt Caching)。系统消息始终处于对话的开头,而用户消息在每轮对话中位置都会发生漂移。将 RAG 上下文移动到系统消息中可确保缓存持续有效,从而实现近乎瞬时的后续追问响应,而无需在每轮对话中重新处理庞大的上下文。

📦 数据库优化

对于大规模部署而言,您的数据库配置是决定系统稳定性的最关键因素。

PostgreSQL(扩容的必需项)

对于任何多用户或高并发的部署场景,必须使用 PostgreSQL。SQLite(默认数据库)并非为了高并发而设计,在高负载下会成为性能瓶颈(引发数据库锁定错误)。

  • 变量名DATABASE_URL
  • 配置示例postgres://user:password@localhost:5432/webui

聊天保存策略

默认情况下,Open WebUI 会在文本生成完全结束之后保存聊天记录。虽然支持实时保存(逐个 token 保存),但这会造成巨大的数据库写入压力,因此强烈不建议启用。

  • 环境变量ENABLE_REALTIME_CHAT_SAVE=False(默认值)
  • 效果:聊天仅在生成结束后(或周期性地)进行保存。
  • 建议切勿在生产环境中开启 ENABLE_REALTIME_CHAT_SAVE 强烈建议将其保持为 False,以防止在并发负载下耗尽数据库连接并导致严重的性能下降。详情请参阅环境变量配置指南

数据库会话共享

自 v0.7.1 起,Open WebUI 包含了数据库会话共享功能。该功能通过复用数据库会话,而非为每个请求都新建会话,从而能够提升高并发下的性能。

  • 环境变量DATABASE_ENABLE_SESSION_SHARING
  • 默认值False
针对不同数据库类型的建议
  • SQLite: 保持此项为禁用状态(默认值)。在硬件资源有限的设备上,对 SQLite 启用会话共享可能会导致严重的性能下降或超时。
  • 资源充足的 PostgreSQL: 建议启用此设置以提升性能,尤其是在多用户或高并发部署中。
低配置硬件

如果您升级到 v0.7.0 后遇到了管理员页面加载缓慢、API 超时或界面无响应的问题,很可能是由于数据库会话共享被默认启用了。请确保在低配置硬件(如树莓派、CPU 配额被限制在 250m 或更低的容器)上设置 DATABASE_ENABLE_SESSION_SHARING=False

连接池大小调整

对于高并发的 PostgreSQL 部署,默认的连接池设置可能不够用。如果您遇到了 QueuePool limit reached 错误或连接超时,请增大连接池:

  • 环境变量DATABASE_POOL_SIZE=15(默认:使用 SQLAlchemy 的默认值)
  • 环境变量DATABASE_POOL_MAX_OVERFLOW=20(默认:0)

重要提示: 两者之和(DATABASE_POOL_SIZE + DATABASE_POOL_MAX_OVERFLOW)应当远低于您数据库的 max_connections 限制。PostgreSQL 默认的最大连接数为 100,因此请将每个 Open WebUI 实例的连接池总数控制在 50-80 以下,以便为其他客户端和维护操作预留空间。

向量数据库(RAG)

对于多用户部署,向量数据库的选择至关重要。

  • ChromaDB(默认):在多 Worker(UVICORN_WORKERS > 1)或多副本部署中是不安全的。默认配置下的 ChromaDB 在本地使用的是由 SQLite 支持的 PersistentClient。SQLite 连接并不符合 fork 安全——当 uvicorn fork 出多个 Worker 进程时,每个进程都会继承同一个数据库连接,并发写入会立使其崩溃(提示 Child process died)或导致数据库损坏。这是 SQLite 底层设计的局限性,而非 Bug。详情请参阅扩容与高可用故障排除指南了解完整的崩溃机制及解决方案。
  • 推荐方案
    • MilvusQdrant:追求更佳的扩容与性能时的最佳选择。它们属于客户端-服务器型数据库,天然支持多进程安全访问。
    • PGVector:如果您已经在运行 PostgreSQL,这会是一个极佳的选择。它同样完全支持多进程安全。
    • ChromaDB HTTP 模式:如果您想继续使用 ChromaDB,请将其作为独立服务器运行,使 Open WebUI 通过 HTTP 连接它,而非在本地使用 SQLite。
  • 多租户(Multitenancy):如果使用 Milvus 或 Qdrant,启用多租户可以提供更好的资源共享。
    • ENABLE_MILVUS_MULTITENANCY_MODE=True
    • ENABLE_QDRANT_MULTITENANCY_MODE=True

内容提取引擎

默认的内容提取器会导致内存泄漏

默认的内容提取引擎使用的是包含 pypdf 在内的 Python 库,这些库在吸纳(ingestion)文档时存在持续的内存泄漏。在经常需要上传文档的生产环境部署中,这会导致 Open WebUI 的内存占用持续增长,直到进程被系统杀死(OOM)或容器重启。

这是生产环境部署中引发不明内存增长的第一大原因

建议:对于需要经常处理文档的任何部署,请切换到外部内容提取引擎:

引擎类型最佳适用场景对应配置
Apache Tika通用型,应用广泛,支持绝大多数文档类型CONTENT_EXTRACTION_ENGINE=tika + TIKA_SERVER_URL=http://tika:9998
Docling高质量提取,支持布局感知解析CONTENT_EXTRACTION_ENGINE=docling
PaddleOCR-vlOCR 密集型工作负载(扫描版 PDF、图像、混合排版);自托管视觉-语言 OCRCONTENT_EXTRACTION_ENGINE=paddleocr_vl + PADDLEOCR_VL_BASE_URL=http://paddleocr-vl:8080 + PADDLEOCR_VL_TOKEN=...
External Loader推荐用于生产环境和自定义的提取流水线CONTENT_EXTRACTION_ENGINE=external + EXTERNAL_DOCUMENT_LOADER_URL=...

使用外部提取器可以将计算密集型的解析工作从 Open WebUI 进程中完全移出,从而彻底根除这类内存泄漏问题。

嵌入向量引擎

大规模部署下的 SentenceTransformers

默认的 SentenceTransformers 嵌入向量引擎(all-MiniLM-L6-v2)会将一个机器学习模型直接加载到 Open WebUI 的进程内存中。虽然这对于个人使用而言非常轻量,但在大规模部署中,该模型:

  • 消耗可观的内存(每个 Worker 进程消耗约 500MB+ 的内存)
  • 在较旧版本上,在执行嵌入操作时会阻塞事件循环
  • 随 Worker 数量成倍增长 —— 每个 Uvicorn Worker 都会加载其独立的一套模型副本

对于多用户或生产环境部署,请将嵌入向量计算外包给外部服务

  • 推荐:使用 RAG_EMBEDDING_ENGINE=openai(通过 OpenAI、Azure 或兼容 API 接入云端向量嵌入)或 RAG_EMBEDDING_ENGINE=ollama(使用本地托管的 Ollama,并配以如 nomic-embed-text 模型来进行嵌入计算)。
  • 环境变量RAG_EMBEDDING_ENGINE=openai
  • 效果:嵌入模型将不再被加载到 Open WebUI 的进程内,从而为每个 Worker 节省数百 MB 的内存。

优化文档切片(Chunking)

文档切片的方式会直接影响存储效率以及召回质量。

  • 使用 Markdown 标题切分器:这能够保留您文档的语义结构。
  • 设置切片最小尺寸目标:在使用 Markdown 标题切分器时,可能会产生极小的切片(例如仅包含一个子标题)。这些切片的存储效率低下,且不利于召回。
    • 环境变量CHUNK_MIN_SIZE_TARGET=1000(示例值)
    • 优势:智能地将小切片与相邻切片合并,这不仅显著降低了向量总数,还提升了 RAG 检索的性能。

📈 基础架构扩容(多租户与 Kubernetes)

如果您要面向企业级规模进行部署(拥有成百上千的用户),简单的 Docker Compose 设置可能难堪重任。您需要将其移入集群环境中运行。

若需查看整个扩容演进(PostgreSQL、Redis、向量数据库、存储、可观测性)的逐步演示,请参阅 扩容 Open WebUI 指南。

  • Kubernetes / Helm:关于在 K8s 上进行多副本部署的配置,请参见 多副本与高可用指南
  • Redis(必需项):当运行多个 Worker(UVICORN_WORKERS > 1)或多个副本时,必须使用 Redis 来处理 WebSocket 连接以及会话同步。参见 Redis 集成
  • 负载均衡:确保您的 Ingress 控制器支持会话亲和性(Session Affinity / 粘性会话),以获取最佳性能。
  • 反向代理缓存:配置您的反向代理(如 Nginx、Caddy、Cloudflare)以缓存静态资源(JS、CSS、Images)。这可以显著减轻应用服务器的负载。参见 Nginx 配置Caddy 配置
  • 禁用代理缓冲(对流式传输至关重要):如果使用 Nginx,您必须为 Open WebUI 禁用 proxy_buffering。代理缓冲会重新打包 SSE 流,导致 Markdown 文本排版错乱以及流式响应延迟卡顿。请在您的 location 块中加入 proxy_buffering off;proxy_cache off;。参见 连接故障排除

⚡ 高并发与网络优化

对于存在大量并发用户的部署,以下设置对于防止出现瓶颈至关重要。

批量流式传输 Token

默认情况下,Open WebUI 会将从 LLM 传来的每一个 Token 都实时流式传输。这种高频流式传输会增加服务器的网络 I/O 以及 CPU 占用。如果同时开启了实时保存(强烈不建议),这还会彻底摧毁数据库的性能。

增大 Chunk 尺寸可以缓冲这些更新,以更大的分组将其发送至客户端。这唯一的副作用是流式显示回答时界面会稍微少一些丝滑感,但在高负载下,它能带来非常显著的性能改观。

  • 环境变量CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE=7
    • 建议:高并发实例建议将其设为 5-10

线程池大小

定义了可用于处理请求的 Worker 线程数量。

  • 默认值:40
  • 高流量建议2000+
  • 警告切勿降低此值。 即使在低配置的硬件上,空闲的线程池也不会占用显著的资源。将其设得太低(例如 10)会导致应用死锁挂起并引发请求超时。
  • 环境变量THREAD_POOL_SIZE=2000

AIOHTTP 客户端超时

超长的 LLM 文本生成可能会超出默认的 HTTP 客户端超时时间。通过配置这些变量以防请求在中途被掐断:

  • 环境变量AIOHTTP_CLIENT_TIMEOUT=1800(针对文本生成提供 30 分钟超时时间)
  • 环境变量AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST=15(拉取模型列表时超时设得短一些)
  • 环境变量AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST=15

容器资源限制

对于 Docker 部署,请确保分配了充足的资源配额:

deploy:
  resources:
    limits:
      memory: 8G      # 根据实际使用情况进行微调
      cpus: '4.0'
    reservations:
      memory: 4G
      cpus: '2.0'

# 调高文件描述符上限
ulimits:
  nofile:
    soft: 65536
    hard: 65536

诊断排查命令:

# 检查容器的实际资源占用
docker stats openwebui --no-stream

# 检查连接的状态分布
docker exec openwebui netstat -an | grep -E "ESTABLISHED|TIME_WAIT|CLOSE_WAIT" | sort | uniq -c

# 检查已打开的文件描述符数量
docker exec openwebui ls -la /proc/1/fd | wc -l

☁️ 云端基础设施延迟

在云端 Kubernetes 环境(如 AKS、EKS、GKE)中部署 Open WebUI 时,您可能会注意到其性能比在本地 Kubernetes(Rancher Desktop、kind、Minikube)或裸金属服务器上部署时有明显的下降——即便分配的资源完全相同。这几乎总是由底层基础设施的**延迟(Latency)**所引发的。

网络延迟(数据库与服务)

最常见的云端性能瓶颈是 Open WebUI 与其数据库之间的网络延迟

许多云端部署方案会将数据库部署在不同的节点、可用区(AZ)甚至是使用托管的数据库服务中。虽然这在架构上非常健壮,但会为每一次数据库查询都引入网络延迟。Open WebUI 在每次请求中都会进行多次数据库调用,因此在高并发负载下,哪怕每次查询仅产生 10-20ms 的网络延迟,累加起来也会导致数秒的响应延迟。

症状:

  • 健康检查(health check)接口响应慢,而非近乎瞬时返回。
  • 在并发负载下,简单的 API 调用或正常的聊天响应都会变得迟钝卡顿,即使此时 CPU 和内存占用看起来很低。
  • 本地开发测试环境与云端生产环境之间存在明显的性能差距。

诊断步骤:

  • 在 Open WebUI pod 内检查与其数据库之间的网络延迟:
    # 针对 PostgreSQL
    psql -h <db-host> -U <user> -c "SELECT 1" -d <database>
    
    # 或者使用 ping/nc 测试原生延迟
    nc -zv <db-host> 5432
  • 理想的延迟指标:数据库查询延迟应当以 1-2ms 或更低为目标。如果连接数据库的网络延迟超过了 5ms,强烈不建议将其用于生产部署,因为这大概率会成为您系统的核心性能瓶颈。

解决方案:

  1. 服务同域部署(Co-locate services):将 Open WebUI 和 PostgreSQL 部署在同一个可用区(AZ)内,如果可能的话,甚至部署在同一个节点池(node pool)中,以使网络跳数(hops)降至最低。
  2. 理性看待托管数据库:请注意,虽然云端的“一键式”托管数据库扩容性强,但与在相同节点上自建数据库相比,托管服务往往会引入显著的网络延迟。必须在架构规划时仔细权衡这一折中。
  3. 启用缓存:通过配置 ENABLE_BASE_MODELS_CACHE=True 以及其他缓存选项以降低查询数据库的频次。
  4. 减少数据库写入:设置 ENABLE_REALTIME_CHAT_SAVE=False 来批量更新数据库,减轻 IOPS 压力。

磁盘 I/O 延迟(SQLite 与存储)

如果您在云环境中使用了 SQLite(默认数据库),您可能正在承受巨大的磁盘延迟

与本地直接挂载的 NVMe/SSD 相比,云存储(如 Azure Disks、AWS EBS、GCP Persistent Disks)往往会有显著增高的延迟以及偏低的 IOPS——尤其是在低阶的存储类型中。

SQLite 官方本身并不支持在 NFS / SMB / Azure Files 上运行 SQLite

这一局限性并非来自于 Open WebUI,而是来自于 SQLite 官方。SQLite 项目明确声明,官方不支持将 SQLite 数据库放在网络文件系统(NFS, SMB/CIFS 及类似协议)上:这些协议上的文件锁定机制极不可靠,且并发写入可能会损坏数据库。SQLite 官方文档对此提出了严厉的警告,由于 Open WebUI 使用了 SQLite,因而自然继承了这一限制。

因此,对于 Open WebUI,唯一受支持的存储配置为

  • PostgreSQL —— 强烈推荐用于任何多用户部署,且如果数据库无法放在直接挂载的本地 SSD 上,则必须配置 PostgreSQL。这能彻底绕开“网络存储上的 SQLite”问题。或者
  • SQLite 放在直接挂载的本地 SSD / NVMe 上 —— 仅适用于单用户或极小规模部署。必须是宿主机上的本地磁盘;无论是什么应用,SQLite 官方的指导原则都是通用的。

SQLite 不支持以下存储类型(根据 SQLite 自身文档,而非 Open WebUI 政策):NFS、SMB/CIFS、Azure Files、GlusterFS、CephFS、基于对象存储的 FUSE 挂载、网络 PVC、任何远程或低 IOPS 存储。 这包含了基于这些文件系统挂载的 Docker 绑定挂载和 Kubernetes PVC。除了下述的性能症状外,您还将面临数据库损坏的风险——这同样是 SQLite 官方的警告。

如果您的存储类型不是本地 SSD/NVMe,请务必配置 PostgreSQL

在升级到使用异步 SQLite 驱动的版本后,常见的典型症状如下:

  • /api/config 请求每次都会耗时 10 到 20 秒以上
  • /api/v1/chats/?page=1 及其他列表接口在负载下挂起长达数分钟
  • OIDC / SSO 登录回调在重定向回 Open WebUI 时无限挂起或“转圈”
  • 在 DEBUG 日志中,aiosqlitehttpcore 的日志行之间存在长达数秒的时间空白
  • 日志中显示 PRAGMA journal_mode=WAL 开始运行但永远无法完成

在较旧的同步 SQLAlchemy 版本(≤ 0.8.12)中,并发竞争在进程内被串行化了,这在一定程度上遮蔽了存储缓慢的问题。而异步驱动会在多个线程间打开连接并高频访问文件系统,使得网络附加存储的性能退化问题瞬间暴露无遗。

为什么异步后端会导致网络存储上的 SQLite 突然失效

如果您从 0.8.x 升级到 0.9.x,且您的部署环境没有做过任何其他改动,下述机制就是导致系统崩溃的原因。非常值得深入理解,因为试图调整 DATABASE_POOL_SIZE 等参数只是舍本逐末,并非根治之策。

最核心的因素在于 fsync() SQLite 保证持久性的机制是每次 Commit 时都执行同步刷盘。而 fsync 的延迟完全取决于文件所处的物理介质:

存储介质典型的 fsync 延迟时间
本地 NVMe~100 μs
本地 SATA SSD100 μs – 几毫秒
本地机械硬盘 (HDD)~10 毫秒
挂载的 NFS / CephFS / Azure Files (基于 SSD)50–500 毫秒
NFS (基于机械硬盘或高延迟网络)数百毫秒至数秒不等

无论代码是同步的还是异步的,这一底层延迟是完全相同的。改变的是同时并发处于在途(in flight)状态的 fsync 数量

旧体系 —— 同步 SQLAlchemy (0.8.x):数据库调用运行在 FastAPI 约 40 个线程的 Worker 线程池中。这个线程池起到了天然的限流作用 —— 您在同一个时刻绝不会并发发起超过 40 个 SQLite 操作。缓慢的存储只是让单个请求变慢,但线程池在底层系统彻底崩溃前起到了反向缓冲保护作用。用户看到的只是“应用运行慢”,而非“应用彻底死掉”。

新体系 —— 异步 aiosqlite (0.9.x):线程池的上限不复存在。asyncio 协程循环并行调度数以千计的数据库协程,每个协程都试图从 SQLAlchemy 异步连接池(默认 pool_size=5 + max_overflow=10 = 15 个连接)中获取连接。在本地 SSD 上,连接被获取、执行 fsync(耗时约 1ms)、归还到池中 —— 连接流转极快,15 个连接槽位绰绰有余。而在 NFS/CephFS 上,同一个连接会因为等待 fsync 刷盘而被阻塞数百毫秒,并在整个过程中持续占用该连接槽位,导致连接池几乎在瞬间达到饱和。此后的每个请求都必须排队等待 pool_timeout(30 秒),超时后报错崩溃:

sqlalchemy.exc.TimeoutError: QueuePool limit of size 5 overflow 10 reached,
connection timed out, timeout 30.00

单纯调大 DATABASE_POOL_SIZE 只是把崩溃点往后推迟了。连接池越大,意味着有越多并发的缓慢 fsync 压向已经非常慢的网络存储 —— 文件系统依然是那根瓶颈,这绝不是单纯靠扩容池子就能解决的。

并且,在 NFS 上运行 WAL 模式更是存在硬性缺陷。 SQLite 的 WAL 模式使用了一个基于 mmap-shm 文件来进行跨进程协作。SQLite 官方说得很直白,NFS 协议上的 mmap 极其不稳定 —— 甚至有些 NFS 版本根本不支持它。在低并发下,它仅仅表现为速度慢;而在异步高并发下,您将遇到严重的死锁和锁定失败(例如死锁、PRAGMA journal_mode=WAL 开始后永远无法完成、简单查询就挂起数分钟)。

为什么说 PostgreSQL 才是解药,而非扩大连接池:因为 PostgreSQL 服务器会针对它自己的本地存储管理它自己的 I/O 并发。虽然您的应用通过网络 Socket 访问它,但这一网络开销比 NFS 上的 fsync 便宜了几个数量级,并且 PostgreSQL 从诞生之初就是为了应对多进程并发写入而设计的 —— 没有文件级的锁定竞争,没有跨进程 mmap 协作,也没有网络文件系统上的 WAL 种种雷区。专用的异步驱动(asyncpg)可以与其直接进行高效的异步通信。当存储无法保证是本地高速盘时,这是唯一能与异步高并发完美配合的数据库架构。

一句话总结:同步后端通过线程池限制了并发上限,因此缓慢的存储只会使系统变。而异步后端允许极大的并发度,这意味着缓慢的 fsync 会不断堆积,导致连接被占用的时间大幅拉长,最终使池子饱和死锁。先前的存储勉强能用,仅仅是因为旧版应用在同一个时间点并没有向其发起 20 个并发的 fsync 写入。

SQLite 对磁盘性能极为敏感,因为它执行的是同步写入。将数据库文件从本地 SSD 移到网络共享盘可能会使单次操作的延迟激增 10 倍以上。

症状:

  • 单个用户使用时性能可以接受,但并发人数增加时系统迅速退化。
  • 尽管 CPU 占用很低,但服务器上出现极高的 "I/O Wait"(I/O 等待)。

解决方案(按健壮性从高到低排列):

  1. 最佳做法 —— 迁移至 PostgreSQL。对于任何非纯单用户本地部署的场景,这都是官方唯一推荐的修复手段;而对于任何运行在远程/网络/低 IOPS 存储上的部署,这属于强制性要求。请配置:
    DATABASE_URL=postgresql+asyncpg://user:password@host:5432/webui
    由于数据库进程拥有独立的存储,PostgreSQL 彻底免除了“每个连接都必须等待磁盘 fsync 完毕”的恶性循环,也是应对多用户负载的唯一支持选项。
  2. 可行做法 —— 将 webui.db 移至直接挂载的本地 SSD/NVMe 上。仅适用于单用户或极小规模的部署。请将宿主机上的本地高速 SSD/NVMe 目录绑定挂载(bind-mount)进容器的 /app/backend/data 路径下。千万不要使用 NFS、SMB、Azure Files 或任何网络附加存储 —— 哪怕是标榜“高性能”的网络块存储也无济于事。SQLite 并非为网络文件系统设计,在其上运行必定缓慢。
  3. 仅限作为临时的折中手段 —— 在 NFS 上以超低并发运行 SQLite。如果您确实无法立即切换数据库或迁移文件,请配置:
    DATABASE_POOL_SIZE=1
    DATABASE_SQLITE_PRAGMA_BUSY_TIMEOUT=30000
    DATABASE_POOL_SIZE=1 会强行将所有数据库连接串行化为单个异步连接,牺牲并发性能以换取稳定性。DATABASE_SQLITE_PRAGMA_BUSY_TIMEOUT=30000 给予了 SQLite 30 秒的锁获取宽限时间(网络文件系统申请锁通常比本地盘慢得多)。这绝非受支持的长期配置 —— 系统仍可能会出现吞吐量下降、间歇性卡顿甚至是数据损坏的风险。请尽快规划迁移至 PostgreSQL 或本地 SSD 上。重启后连接池在短期内可能看起来正常,但在负载增加时问题依然会卷土重来。
  4. 云端块存储:当在云上挂载 Open WebUI 数据卷(用于 PostgreSQL 或者是应用本身)时,请使用基于 SSD 的**块存储(Block Storage)**类型(例如 Azure 上的 Premium_LRS、AWS 上的 gp3、GCP 上的 pd-ssd)。对于任何包含数据库读写(包括 SQLite)的工作负载,都应当避开“文件(File)”类型的网络共享卷(如 azurefile-csi)。

其他云端特定的考量因素

基础设施因素对系统的影响缓解/应对策略
突发型虚拟机(如 Azure B 系列、AWS T 系列)在持续高负载下 CPU 会被强行降频限制,即使系统报出来的占用率并不高选用标准型或计算优化型的节点池
DNS 解析开销每次发起外部网络请求都会产生 CoreDNS 的解析延迟确保 CoreDNS 的扩容与配置正确;考虑启用节点本地 DNS 缓存(node-local DNS cache)
服务网格 SidecarIstio/Linkerd 等服务网格代理会为每个请求添加额外的路由延迟检查并精简您 Pod 中包含的 Sidecar 容器
网络策略约束CNI 插件处理网络封包的损耗审核并尽可能精简容器间的网络策略配置
跨可用区流量当服务跨可用区部署时,会引入微小的延迟以及跨区传输成本尽量将互锁的关联服务绑定在同一个可用区(AZ)内

降低资源占用(减少内存)

如果在内存极其受限的设备上部署(如树莓派、小配置 VPS),请采用以下策略以防止应用程序因内存耗尽(OOM)而崩溃。

1. 卸载辅助模型(仅限本地部署)

Open WebUI 会加载本地的机器学习模型来支持 RAG 和语音转文字等功能。仅当您在本地运行这些模型时,本章节才适用。

RAG 嵌入向量

  • 低配置建议

    • 方案 A(最简便):保持使用默认的 SentenceTransformers(all-MiniLM-L6-v2)。它非常轻量,可以直接运行在 CPU 上,比在同一个树莓派上同时多跑一个 Ollama 要节省得多。
    • 方案 B(性能最佳):使用外部 API(云端/外部嵌入向量服务)。
  • 配置选项

    • Admin PanelSettings > Documents > Embedding Model Engine
    • 环境变量RAG_EMBEDDING_ENGINE=openai(彻底移出本地内存占用)

语音转文字(STT)

本地的 Whisper 模型非常重(会白白占用 ~500MB+ 的内存)。

  • 建议:使用 WebAPI(基于浏览器的语音识别)。它会直接利用用户客户端设备的计算能力,完全不消耗服务器的内存。

  • 配置方法

    • Admin PanelSettings > Audio > STT Engine
    • 环境变量AUDIO_STT_ENGINE=webapi
  • 绕过音频预处理(外包给 STT 提供商):如果您使用外部 STT 引擎(如 OpenAI、Deepgram、Azure、Mistral),这些引擎已经能够接收原始音频并自动处理格式转换。此时请设置 BYPASS_PYDUB_PREPROCESSING=true。这会跳过 Open WebUI 基于 pydub 库的 MP3 转换、压缩和分片逻辑,从而省去了每次上传音频时的 CPU 密集型开销,免去了 ffmpeg 依赖,并能显著缩短大文件的上传响应延迟。仅在您确认上游提供商能够妥善处理未经处理的音频时,才关闭此预处理。

2. 禁用未使用的功能

防止应用加载您根本用不到的本地模型。

  • 图像生成ENABLE_IMAGE_GENERATION=False(管理员界面:Settings > Images
  • 代码解释器ENABLE_CODE_INTERPRETER=False(管理员界面:Settings > Tools

3. 禁用后台任务

如果资源占用极其敏感,请禁用那些会持续触发模型推理的自动功能。

建议禁用顺序(按成效从大到小排列):

  1. 自动补全(Autocomplete)ENABLE_AUTOCOMPLETE_GENERATION=False影响最大:因为用户每敲击一次键盘都会触发模型推理!)
    • 管理员界面:Settings > Interface > Autocomplete
  2. 后续追问(Follow-up)建议ENABLE_FOLLOW_UP_GENERATION=False
    • 管理员界面:Settings > Interface > Follow-up
  3. 自动生成聊天标题ENABLE_TITLE_GENERATION=False
    • 管理员界面:Settings > Interface > Chat Title
  4. 自动生成标签(Tags)ENABLE_TAGS_GENERATION=False

预设 1:极度隐私(弱硬件/树莓派)

适用场景:100% 纯本地、树莓派或内存少于 4GB 的设备。

  1. 嵌入向量:保持默认(SentenceTransformers)- 轻量级,运行在 CPU 上。
  2. 音频处理AUDIO_STT_ENGINE=webapi - 服务器端完全零资源开销。
  3. 后台任务模型:完全禁用,或使用极小的本地模型(如 llama3.2:1b)。
  4. 连接池:保持默认的 THREAD_POOL_SIZE (40)。
  5. 禁用项:图像生成、代码解释器、自动补全、后续追问建议。
  6. 数据库:SQLite 即可胜任。

预设 2:单用户发烧友

适用场景:追求极致的生成质量与速度,混用本地与外部云端 API。

  1. 嵌入向量RAG_EMBEDDING_ENGINE=openai(如果服务器足够快,也可用 ollama 并搭载 nomic-embed-text)。
  2. 后台任务模型gpt-5-nanollama-3.1-8b-instant
  3. 缓存机制MODELS_CACHE_TTL=300
  4. 数据库ENABLE_REALTIME_CHAT_SAVE=False(即使是个人使用,也强烈建议保持禁用以换取极佳的稳定性)。
  5. 向量数据库:推荐 PGVector,或者使用 ChromaDB 都可以(除非要处理非常庞大的数据量)。

预设 3:大规模 / 企业级

适用场景:服务于海量并发用户,相比强行维护而导致连接阻塞,稳定运行高于一切。

  1. 数据库PostgreSQL(强制项)。
  2. 文档内容提取TikaDocling(强制项 —— 默认的 pypdf 存在严重的内存泄漏问题)。参见内容提取引擎
  3. 嵌入向量外部服务 —— RAG_EMBEDDING_ENGINE=openaiollama(强制项 —— 默认的 SentenceTransformers 会在大流量下吃掉太多服务器内存)。参见嵌入向量引擎
  4. 工具调用模式Native Mode(强制项 —— 默认的 Prompt-based 模式已被弃用,它不仅会严重破坏 KV 缓存而导致延迟飙升,还无法使用系统内置工具)。请确保所有模型都配置为了 Native 模式。参见工具调用模式
  5. Worker 线程THREAD_POOL_SIZE=2000(防止超长等待导致超时)。
  6. 流式ChunkCHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE=7(显著降低 CPU/网络/数据库 的频繁写入损耗)。
  7. 历史记录保存ENABLE_REALTIME_CHAT_SAVE=False
  8. 向量数据库MilvusQdrantPGVector严禁在多 Worker 或多副本部署中使用 ChromaDB 的默认本地模式 —— 它是基于 SQLite 实现的,在并发写入下会瞬间引发 Worker 崩溃。
  9. 任务模型:云端托管 API(彻底卸载本地的 CPU/显存 开销)。
  10. 缓存机制ENABLE_BASE_MODELS_CACHE=TrueMODELS_CACHE_TTL=300ENABLE_QUERIES_CACHE=True
  11. Redis 配置:普通的单实例即可,配以 timeout 1800 和高 maxclients (10000+)。参见下方的 Redis 调优

Redis 调优

对于绝大多数部署环境(包括服务于数万名用户的环境),单独一个 Redis 实例就已经完全足够了。您几乎不需要部署 Redis Cluster 或 Redis Sentinel,除非您有特定的极高可用性(HA)架构要求。

通常会导致不必要扩容的 Redis 配置缺陷如下表所示:

错误配置缺陷引发的症状对应的修复方法
连接长期挂起不释放Redis 连接数爆满或内存无上限增长在 redis.conf 中配置 timeout 1800(强制在闲置 30 分钟后关闭连接)
maxclients 偏低max number of clients reached 错误设置 maxclients 10000 或更高
没有客户端连接上限控制Open WebUI 的 Pod 会积攒永远不会释放的连接建议在 Redis 客户端配置中,结合 timeout 设置连接池上限

⚠️ 常见反模式

以下是现实世界中导致企业过度配置且浪费大量计算资源的常见典型技术陷阱:

典型反模式带来的后果对应的正确修复方案
在生产环境下使用默认内容提取引擎pypdf 持续泄露内存 → 容器因 OOM 不断重启 → 企业被迫不断添加副本以作缓冲切换到 Tika 或 Docling(如 CONTENT_EXTRACTION_ENGINE=tika
大规模运行 SentenceTransformers每个 Worker 都要平白加载约 500MB 的模型 → 内存占用暴增 → 被迫买更多服务器使用外部的向量嵌入 API(如 RAG_EMBEDDING_ENGINE=openaiollama
单 Redis 够用却盲目上 Redis Cluster副本数膨胀 → 连接数剧增 → Redis 无法承受 → 又加配 Redis 集群来硬抗解决根源问题(精简副本数、配置 timeout 1800、设定 maxclients 10000
试图通过增加副本数来掩盖内存泄漏进程依旧泄露内存 → 照样被 OOM 强杀 → 自动缩放不断拉起新 Pod → Redis 连接被瞬间爆满挂掉优先解决内存泄漏根源(改用外部提取引擎和嵌入向量),然后再合理配置资源大小
使用旧版(基于提示词 prompt)的工具调用此模式被弃用且已不再受支持;注入过长提示词会摧毁 KV 缓存导致延迟激增,且无法接入系统内置工具请务必将每一个模型都切换为 Native Mode
未配置 Redis 的长期闲置连接超时连接只增不减永远堆积 → Redis 发生 OOM 崩溃在 redis.conf 中加入 timeout 1800
在 Actions / Filters 插件中使用 Base64 编码的图标图标数据会被直接塞进 /api/models 接口响应中,用户每次加载页面获取模型列表时都得下载这些冗长的 Base64。假设 20 个模型配有 3 个 Action 插件,每个图标 500 KB,这会导致单次接口响应体无端膨胀 30 MB → 前端加载极其缓慢,带宽带宽被白白浪费,服务器面临极大的内存处理压力将图标托管为静态静态文件,并在代码中通过 URL 指向 icon_urlself.icon。参见自定义 Action 函数的 icon_url 警告提示

🔗 环境变量参考手册

有关所有可用环境变量的详细信息,请参阅环境变量配置指南。

环境变量名说明及详细配置链接
TASK_MODELTask Model (Local) 任务模型(本地)
TASK_MODEL_EXTERNALTask Model (External) 任务模型(外部)
ENABLE_BASE_MODELS_CACHECache Model List 缓存模型列表
MODELS_CACHE_TTLModel Cache TTL 模型缓存 TTL
ENABLE_QUERIES_CACHEQueries Cache 查询缓存
DATABASE_URLDatabase URL 数据库连接 URL
ENABLE_REALTIME_CHAT_SAVERealtime Chat Save 实时保存聊天记录
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZEStreaming Chunk Size 流式传输分组大小
THREAD_POOL_SIZEThread Pool Size 线程池大小
RAG_EMBEDDING_ENGINEEmbedding Engine 向量嵌入引擎
CONTENT_EXTRACTION_ENGINEContent Extraction Engine 内容提取引擎
AUDIO_STT_ENGINESTT Engine 语音转文字引擎
BYPASS_PYDUB_PREPROCESSINGBypass pydub audio preprocessing 绕过 pydub 音频预处理
ENABLE_IMAGE_GENERATIONImage Generation 启用图像生成
ENABLE_AUTOCOMPLETE_GENERATIONAutocomplete 自动补全
RAG_SYSTEM_CONTEXTRAG System Context RAG 系统上下文注入
DATABASE_ENABLE_SESSION_SHARINGDatabase Session Sharing 数据库会话共享
This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.