WebSocket 架构(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/15.1-websocket-architecture
翻译时间:2026-06-09T16:11:37.621Z
翻译模型:deepseek-chat
原文字符数:10338
项目:Open WebUI (open-webui)
---
WebSocket 架构
相关源文件
以下文件为本 wiki 页面的生成上下文:
backend/open_webui/socket/main.pybackend/open_webui/socket/utils.pybackend/open_webui/tasks.pybackend/open_webui/test/util/test_redis.pybackend/open_webui/utils/rate_limit.pybackend/open_webui/utils/redis.py
目的与范围
本文档介绍 Open WebUI 中基于 Socket.IO 的 WebSocket 服务器架构,涵盖服务器配置、连接生命周期、认证、房间管理及事件路由模式。WebSocket 层支持实时功能,包括 AI 响应流式传输、协同文档编辑(Yjs)、带输入状态提示的频道消息以及任务进度更新。
---
Socket.IO 服务器初始化
服务器配置
Socket.IO 服务器在 backend/open_webui/socket/main.py backend/open_webui/socket/main.py:1-98 中初始化,支持 WebSocket 和 HTTP 长轮询两种传输方式。服务器可独立运行,也可通过 AsyncRedisManager backend/open_webui/socket/main.py:65-84 使用 Redis 支持多实例部署。
标准服务器配置:
backend/open_webui/socket/main.py:86-96
sio = socketio.AsyncServer(
cors_allowed_origins=SOCKETIO_CORS_ORIGINS,
async_mode='asgi',
transports=(['websocket'] if ENABLE_WEBSOCKET_SUPPORT else ['polling']),
allow_upgrades=ENABLE_WEBSOCKET_SUPPORT,
always_connect=True,
logger=WEBSOCKET_SERVER_LOGGING,
ping_interval=WEBSOCKET_SERVER_PING_INTERVAL,
ping_timeout=WEBSOCKET_SERVER_PING_TIMEOUT,
engineio_logger=WEBSOCKET_SERVER_ENGINEIO_LOGGING,
)
基于 Redis 的服务器配置:
backend/open_webui/socket/main.py:65-84
if WEBSOCKET_MANAGER == 'redis':
if WEBSOCKET_SENTINEL_HOSTS:
mgr = socketio.AsyncRedisManager(
get_sentinel_url_from_env(WEBSOCKET_REDIS_URL, WEBSOCKET_SENTINEL_HOSTS, WEBSOCKET_SENTINEL_PORT),
redis_options=WEBSOCKET_REDIS_OPTIONS,
)
else:
mgr = socketio.AsyncRedisManager(WEBSOCKET_REDIS_URL, redis_options=WEBSOCKET_REDIS_OPTIONS)
sio = socketio.AsyncServer(
# ... 同上选项
client_manager=mgr,
)
配置参数
| 参数 | 环境变量 | 用途 |
|---|---|---|
transports | ENABLE_WEBSOCKET_SUPPORT | 启用的协议(轮询/WebSocket) backend/open_webui/socket/main.py:76 |
ping_interval | WEBSOCKET_SERVER_PING_INTERVAL | 心跳包发送间隔(秒) backend/open_webui/socket/main.py:81 |
ping_timeout | WEBSOCKET_SERVER_PING_TIMEOUT | 超时时间(秒) backend/open_webui/socket/main.py:82 |
client_manager | WEBSOCKET_MANAGER | 多实例 Redis 管理器 backend/open_webui/socket/main.py:65 |
来源: backend/open_webui/socket/main.py:63-96, backend/open_webui/env.py:25-41
---
认证与会话管理
两阶段认证
Open WebUI 为 Socket.IO 连接实现了两阶段认证模式:
- 阶段 1:连接时认证(
connect事件)backend/open_webui/socket/main.py:306-327 - 阶段 2:用户加入认证(
user-join事件)backend/open_webui/socket/main.py:328-363
阶段 1:连接事件 初始 connect 事件处理器使用 decode_token backend/open_webui/utils/auth.py:42 验证 auth 参数中的 JWT 令牌,并填充 SESSION_POOL backend/open_webui/socket/main.py:306-327。
阶段 2:用户加入事件 连接后,客户端发送 user-join 事件以完成初始化、加入频道并接收初始用户状态 backend/open_webui/socket/main.py:328-363。
会话与使用池
系统维护多个池来跟踪活跃用户及其活动。这些池根据 WEBSOCKET_MANAGER 设置 backend/open_webui/socket/main.py:105-165 可以是本地字典或 RedisDict 实例 backend/open_webui/socket/utils.py:44-123。
| 池名称 | 代码实体 | 用途 |
|---|---|---|
SESSION_POOL | SESSION_POOL | 将 sid 映射到用户元数据 backend/open_webui/socket/main.py:123-128 |
USAGE_POOL | USAGE_POOL | 跟踪每个会话的活跃模型使用情况 backend/open_webui/socket/main.py:129-134 |
MODELS | MODELS | 缓存的模型定义 backend/open_webui/socket/main.py:116-121 |
会话清理: periodic_session_pool_cleanup 函数 backend/open_webui/socket/main.py:173-194 会清理在 SESSION_POOL_TIMEOUT(120 秒)backend/open_webui/socket/main.py:101 内未发送心跳的孤立会话。
来源: backend/open_webui/socket/main.py:101-165, backend/open_webui/socket/main.py:173-194, backend/open_webui/socket/utils.py:44-123
---
基于房间的事件路由
Socket.IO 房间提供隔离的事件通道。Open WebUI 使用特定的房间命名约定来路由消息:
| 房间模式 | 代码实现 | 用途 |
|---|---|---|
user:{user_id} | sio.enter_room(sid, f"user:{user.id}") | 定向用户事件 backend/open_webui/socket/main.py:325 |
channel:{channel_id} | sio.enter_room(sid, f"channel:{channel.id}") | 群组消息 backend/open_webui/socket/main.py:361 |
doc_{document_id} | sio.enter_room(sid, f"doc_{document_id}") | Yjs 文档编辑 backend/open_webui/socket/main.py:488 |
事件广播模式
服务器使用多个辅助函数来广播事件:
emit_to_users:通过向多个用户的个人房间发送事件来广播backend/open_webui/socket/main.py:260-274。get_event_emitter:创建一个闭包,用于将 AI 响应流式传输到特定用户的房间backend/open_webui/socket/main.py:718-836。get_event_call:使用带超时的sio.call()实现请求-响应模式backend/open_webui/socket/main.py:838-861。
来源: backend/open_webui/socket/main.py:260-274, backend/open_webui/socket/main.py:325-361, backend/open_webui/socket/main.py:718-861
---
分布式任务管理
在多节点环境中运行时,任务(如长时间运行的 AI 生成)必须能在实例间管理。系统使用 Redis Pub/Sub 进行分布式任务控制 backend/open_webui/tasks.py:25-42。
分布式任务命令流程
graph TD
subgraph "Node_A_[请求处理器]"
CT["create_task()"]
RS["redis_save_task()"]
end
subgraph "Redis_后端"
RTK["REDIS_TASKS_KEY"]
RPS["REDIS_PUBSUB_CHANNEL"]
end
subgraph "Node_B_[任务所有者]"
RL["redis_task_command_listener()"]
LT["local_task.cancel()"]
end
CT --> RS
RS --> RTK
NodeA_Stop["stop_task()"] --> RSC["redis_send_command()"]
RSC --> RPS
RPS --> RL
RL --> LT
关键任务函数:
create_task(redis, coroutine, id):生成一个asyncio.Task并在 Redis 中注册backend/open_webui/tasks.py:104-124。stop_task(redis, task_id):通过 Redis Pub/Sub 向所有实例发送“停止”命令backend/open_webui/tasks.py:145-180。redis_task_command_listener(app):监听停止命令并取消本地任务backend/open_webui/tasks.py:25-42。
来源: backend/open_webui/tasks.py:20-180
---
Redis 集成与同步
连接管理
get_redis_connection 工具函数 backend/open_webui/utils/redis.py:179-253 提供了一个带缓存的健壮连接工厂,支持:
- 独立 Redis:通过
REDIS_URL直接连接。 - Redis Sentinel:通过
SentinelRedisProxybackend/open_webui/utils/redis.py:33-150实现自动故障转移的高可用支持。 - Redis 集群:通过
REDIS_CLUSTER环境标志backend/open_webui/env.py:11实现分布式存储。
Redis 架构抽象
classDiagram
class SentinelRedisProxy {
-sentinel: Sentinel
-service: str
-_master()
+__getattr__(item)
}
class RedisDict {
+name: str
+redis: Redis
+__setitem__(key, value)
+__getitem__(key)
}
class YdocManager {
-redis: Redis
+append_to_updates(doc_id, update)
-_compact_updates_redis(doc_id)
}
SentinelRedisProxy ..> RedisDict : 包装连接
RedisDict ..> YdocManager : 概念数据存储
get_redis_connection --* SentinelRedisProxy : 创建
来源: backend/open_webui/utils/redis.py:26-253, backend/open_webui/socket/utils.py:9-228
协同编辑(Yjs)
YdocManager backend/open_webui/socket/utils.py:124-228 使用 pycrdt(Yjs)处理协同文档(笔记)的同步。它支持:
- 更新缓冲:将二进制更新追加到 Redis 列表
backend/open_webui/socket/utils.py:137-147。 - 滚动压缩:当达到
COMPACTION_THRESHOLD(500)时,将更新压缩为快照以优化性能backend/open_webui/socket/utils.py:152-166。
来源: backend/open_webui/socket/utils.py:124-228
---
速率限制
Open WebUI 包含一个 RateLimiter backend/open_webui/utils/rate_limit.py:6-136,采用滑动窗口策略。它优先使用 Redis 在节点间共享状态,但如果 Redis 不可用,则回退到内存中的 _memory_store backend/open_webui/utils/rate_limit.py:13。
实现细节:
- 桶分辨率:默认使用 60 秒桶
backend/open_webui/utils/rate_limit.py:33。 - Redis 策略:使用
INCR操作桶键,并使用MGET计算窗口内的总量backend/open_webui/utils/rate_limit.py:78-92。
来源: backend/open_webui/utils/rate_limit.py:6-136