🔗 Redis WebSocket 支持
本教程由社区贡献,不受 Open WebUI 团队官方维护或审核。它仅作为演示,说明如何根据你的具体场景自定义 Open WebUI。想参与贡献?请查看贡献教程。
概述
本文介绍将 Redis 与 Open WebUI 集成以支持 WebSocket 所需的步骤。按照这些步骤操作,您将能够在 Open WebUI 实例中启用 WebSocket 功能,实现客户端与应用之间的实时通信和更新。
何时需要 Redis?
Redis 在 Open WebUI 中服务于两个不同的目的,了解何时需要它对于正确部署至关重要。有关所有扩展要求(PostgreSQL、Redis、向量数据库、存储)的高层概述,请参阅 扩展 Open WebUI 指南。
单实例部署
如果您以单实例模式运行 Open WebUI,UVICORN_WORKERS=1(默认值),则基本功能不需要 Redis。大多数操作不依赖 Redis 就能正常运行。
没有 Redis 时,登出不会使用户的 JWT 令牌失效。该令牌将保持有效,直到自然过期(默认:4 周)。密码更改和管理员主动封禁账户也无法在没有 Redis 的情况下撤销现有令牌。
对于面向生产的部署,请配置 Redis 或缩短 JWT_EXPIRES_IN 以限制暴露窗口。有关详情,请参阅 安全加固指南。
多 Worker 和多实例部署
在以下场景中 Redis 是必需的:
-
多个 Uvicorn Worker(
UVICORN_WORKERS > 1)- 在单一宿主机上运行多个 Worker 进程
- 需要 Redis 在 Worker 之间共享会话状态和应用配置
-
多节点部署
- 具有多个 Pod 的 Kubernetes 集群
- 具有多个副本的 Docker Swarm
- 具有多个 Open WebUI 实例的负载均衡设置
- 需要 Redis 协调所有实例之间的状态
-
高可用设置
- 任何多个 Open WebUI 进程同时运行的部署模式
- 需要 Redis 进行会话管理、WebSocket 协调和状态同步
关键要求
在多 Worker 或多实例场景中没有 Redis,您将会遇到:
- 跨 Worker 的会话管理失败
- 实例间应用状态不一致
- WebSocket 连接无法正常工作
- 间歇性认证失败
- 实时聊天更新丢失
前提条件
- 一个有效的 Open WebUI 实例(运行 1.0 或更高版本)
- 一个 Redis 容器(本示例使用
redis:7-alpine) - 系统上已安装 Docker Compose(版本 2.0 或更高)
- 用于 Open WebUI 和 Redis 通信的 Docker 网络
- 对 Docker、Redis 和 Open WebUI 有基本了解
关键:Redis 服务器配置
防止“达到最大客户端数”错误
在配置 Open WebUI 使用 Redis 之前,您必须确保 Redis 服务器本身配置正确。一个常见的错误配置会导致连接随时间累积,最终耗尽连接限制,导致完全认证失败(所有用户均得到 500 Internal Server Error)。
问题所在:
Open WebUI 使用 Redis 进行:
- 令牌验证/撤销检查(每次认证请求)
- WebSocket 管理(实时更新)
- 会话存储(如果启用了
ENABLE_STAR_SESSIONS_MIDDLEWARE)
在某些发行版上使用 Redis 默认设置(maxclients 1000、timeout 0)时,连接永远不会关闭。这些连接在数天或数周内默默累积,直到达到限制。然后,突然所有用户都无法登录。
症状:
- 应用程序正常运行数天/数周
- 突然所有用户登录时都得到 500 Internal Server Error
- 日志中出现错误:
redis.exceptions.ConnectionError: max number of clients reached - 随着旧连接最终断开,故障可能临时“自愈”,然后再次失败
解决方案:
将以下设置添加到您的 Redis 配置中:
# 允许足够的并发连接
maxclients 10000
# 30 分钟后关闭空闲连接(1800 秒)
# 这不会影响会话有效性,只影响到 Redis 的 TCP 连接
timeout 1800
Docker 部署时,将以下内容添加到 Redis 命令中:
services:
redis:
image: redis:7-alpine
command: "redis-server --save 30 1 --maxclients 10000 --timeout 1800"
# ... 其余配置为何 timeout 1800 是安全的:
这个超时只影响空闲的 Redis TCP 连接,而不影响用户会话。当连接超时时:
- 用户的 JWT 令牌仍然有效
- 其会话不受影响
- 下一次请求只需重新打开 Redis 连接(增加约 1-5ms,几乎无感知)
监控:
检查当前连接数:
redis-cli INFO clients | grep connected_clients配置正确的 timeout 后,该数字应自然波动(活跃时段上升,安静时段下降),而非无限增长。
设置 Redis
要为 WebSocket 支持配置 Redis,需要创建一个包含以下内容的 docker-compose.yml 文件:
services:
redis:
image: redis:7-alpine
container_name: redis
volumes:
- redis-data:/data
command: "redis-server --save 30 1 --maxclients 10000 --timeout 1800"
healthcheck:
test: "[ $$(redis-cli ping) = 'PONG' ]"
start_period: 5s
interval: 1s
timeout: 3s
retries: 5
restart: unless-stopped
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
- DAC_OVERRIDE
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
networks:
- openwebui-network
volumes:
redis-data:
networks:
openwebui-network:
external: true注意事项
此配置中未包含 ports 指令,因为大多数情况下不需要。Redis 服务仍可在 Docker 网络内被 Open WebUI 服务访问。但是,如果需要从 Docker 网络外部访问 Redis 实例(例如用于调试或监控),可以添加 ports 指令来暴露 Redis 端口(例如 6379:6379)。
上述配置会创建一个名为 redis 的 Redis 容器,并挂载一个持久化数据的卷。healthcheck 指令确保容器在无法响应 ping 命令时重启。--save 30 1 命令选项会在至少 1 个键发生更改时,每 30 分钟将 Redis 数据库保存到磁盘。
重要提示: --maxclients 10000 --timeout 1800 标志用于防止连接耗尽。详情请参阅上方的"关键:Redis 服务器配置"部分。
WebSocket Pub/Sub 缓冲区限制
当 WEBSOCKET_MANAGER=redis 启用时,Open WebUI 通过 Redis Pub/Sub 使用 Socket.IO。流式响应和工具事件可能产生较大的 WebSocket 事件,因为部分更新会包含累积的消息状态,而不仅仅是最新的 token 增量。如果 Redis 在传递这些事件时断开了 Pub/Sub 客户端,用户可能会看到流停滞、实时更新丢失,或日志中出现类似以下的消息:
Cannot publish to redis... retrying
Cannot publish to redis... giving up
redis.exceptions.TimeoutError: Timeout connecting to server可通过以下方式检查 Redis 是否因输出缓冲区限制而断开了 Pub/Sub 客户端:
redis-cli INFO stats | grep client_output_buffer_limit_disconnections
redis-cli SLOWLOG GET 50
redis-cli CONFIG GET client-output-buffer-limit如果慢日志中出现较大的 PUBLISH socketio ... 负载,并且 client_output_buffer_limit_disconnections 计数持续增加,则应提高 Redis 的 Pub/Sub 输出缓冲区限制。例如:
# 保持普通客户端不变;允许更大的 WebSocket Pub/Sub 突发流量。
client-output-buffer-limit normal 0 0 0 replica 268435456 67108864 60 pubsub 1073741824 268435456 180
上述配置将 Pub/Sub 硬上限设为 1 GB,软上限设为 256 MB,持续 180 秒。请根据你的 Redis 可用内存与预期的 WebSocket 负载大小调整这些数值。较高的限制会让 Redis 对临时较慢的订阅者更具容忍度,但同时也会让每个较慢的 Pub/Sub 客户端在被 Redis 断开前缓存更多内存。
如果你是运行时修改的 Redis 配置,可通过以下命令验证当前生效的值:
redis-cli CONFIG GET client-output-buffer-limit要为 Open WebUI 和 Redis 之间的通信创建 Docker 网络,运行以下命令:
docker network create openwebui-network配置 Open WebUI
要在 Open WebUI 中启用 Redis 支持,需要根据部署类型配置不同的环境变量。
基本配置(所有部署)
对于使用 Redis 的所有部署(单实例或多实例),设置以下基本环境变量:
REDIS_URL="redis://redis:6379/0"此变量配置用于应用状态管理、会话存储和实例间协调的主要 Redis 连接。
WebSocket 配置
要专门启用 WebSocket 支持,添加以下额外的环境变量:
ENABLE_WEBSOCKET_SUPPORT="true"
WEBSOCKET_MANAGER="redis"
WEBSOCKET_REDIS_URL="redis://redis:6379/1"WebSocket 连接中一个非常常见且难以调试的问题是跨源资源共享(CORS)策略配置错误。如果您的 Open WebUI 实例从与后端不同的域或端口访问(例如在反向代理后面),您必须设置 CORS_ALLOW_ORIGIN 环境变量。该变量告知服务器哪些源被允许访问其资源。
如果未正确配置,WebSocket 连接将静默失败或出现浏览器中晦涩难懂的错误,而忘记设置此变量是 WebSocket 连接问题的常见原因。
示例:
如果您通过 https://my-open-webui.com 访问 UI,必须设置:
CORS_ALLOW_ORIGIN="https://my-open-webui.com"您也可以提供以分号分隔的允许域列表。在生产环境或反向代理设置中请勿跳过此步骤。
Redis 数据库编号
注意 URL 中不同的数据库编号(/0 与 /1):
REDIS_URL使用数据库0用于通用应用状态WEBSOCKET_REDIS_URL使用数据库1用于 WebSocket 专用数据
这种分离有助于隔离不同类型的数据。如果您愿意,可以对两者使用相同的数据库编号,但使用单独的数据库有助于更好地组织和潜在的性能优化。