金融数据服务的商业化定价一直是个人投资者和小型机构的痛点 —— 主流终端动辄数千美元的年费将大量用户拒之门外。OpenStock 作为开源替代方案,通过 TypeScript 全栈架构实现了实时价格追踪、个性化告警和多源数据聚合三大核心能力。本文将深入其技术架构的关键决策点,特别是实时推送技术选型与数据管道设计,为构建同类系统提供可落地的工程参考。
实时推送技术选型:SSE 与 WebSocket 的决策矩阵
实时行情系统的首要技术决策是选择何种推送机制。OpenStock 类平台通常面临三种选项:短轮询、Server-Sent Events (SSE) 和 WebSocket。短轮询虽然实现简单,但会造成大量无效请求和延迟累积;SSE 和 WebSocket 才是生产环境的可行方案。
SSE 基于 HTTP/1.1 协议,采用单向服务器推送模式。其最大优势在于自动重连机制——EventSource API 在连接断开后会自动尝试恢复,无需开发者编写复杂的重连逻辑。同时,SSE 天然兼容 HTTP/2 的多路复用,可规避浏览器对同一域名的并发连接数限制(HTTP/1.1 下通常为 6 个)。对于仅需接收行情推送的只读场景,如大盘指数展示、涨跌幅排行榜等,SSE 的轻量特性使其成为首选。
WebSocket 则提供全双工通信能力,适合需要客户端向服务器发送指令的交互场景。在股票交易系统中,下单、撤单、修改止盈止损等操作都依赖双向通道。但 WebSocket 的实现复杂度显著更高:需要手动处理连接生命周期、心跳检测、断线重连和消息队列。此外,WebSocket 绕过标准 HTTP 安全机制,存在跨站 WebSocket 劫持风险,需要额外的鉴权设计。
选型建议:采用混合架构 ——SSE 承载公共行情广播(市场数据、新闻推送),WebSocket 处理用户私有交互(交易指令、持仓更新)。这种分层设计既能降低 SSE 端的资源消耗,又能将 WebSocket 连接限制在必要的认证会话范围内。
多源数据聚合的工程实现
免费行情数据源的可靠性是开源平台的核心挑战。OpenStock 需要从 Finnhub、TradingView 等第三方 API 获取数据,并处理不同供应商的数据格式差异和频率限制。
数据管道的典型架构包含四层:
数据摄取层负责与外部 API 建立连接。建议为每个数据源配置独立的速率限制器,避免触发供应商的限流策略。例如 Finnhub 免费档的 WebSocket 连接限制为每秒 1 条消息,REST API 则按分钟配额计费。
归一化层将异构数据转换为统一格式。不同供应商对价格精度的表示可能不同(有的用分,有的用元),时间戳格式也可能存在时区差异。这一层需要维护一个映射表,将原始字段转换为内部标准 Schema(如 symbol、price、volume、timestamp、change_percent)。
聚合层处理数据合并与去重。当多个源同时提供同一标的的价格时,需要定义优先级策略(如优先使用延迟更低的源)或加权平均算法。同时,该层负责计算衍生指标,如涨跌幅、成交量加权平均价 (VWAP) 等。
分发层通过 SSE 或 WebSocket 将数据推送到前端。这里需要引入背压 (backpressure) 机制 —— 当客户端处理速度跟不上数据产生速度时,服务器应丢弃过期数据而非堆积内存。
个性化告警系统的设计
告警功能是 OpenStock 区别于简单行情展示的关键。工程实现上,告警引擎需要在服务端运行,而非依赖前端轮询。
告警系统的核心组件包括:
规则引擎负责解析用户定义的触发条件。支持的条件类型应包括价格阈值(高于 / 低于目标价)、涨跌幅百分比、成交量异动等。规则存储建议使用 Redis 或内存数据库,保证毫秒级查询延迟。
匹配器订阅实时数据流,将每条行情与活跃规则进行比对。这里可以采用布隆过滤器 (Bloom Filter) 预先筛选,避免对无关规则进行完整计算。
通知器在条件触发后执行推送。除了应用内通知,还应支持邮件、Webhook 等外部渠道。为防止告警风暴,需要实现冷却期机制 —— 同一规则在触发后 5 分钟内不应重复通知。
持久化层记录告警历史,用于后续分析和用户行为优化。
可落地的技术参数与部署建议
基于上述架构,以下是可直接落地的配置参数:
SSE 端点配置:
- 心跳间隔:30 秒(保持 NAT 网关连接活跃)
- 重连退避:初始 1 秒,最大 30 秒,指数退避
- 单连接并发流:HTTP/2 环境下建议不超过 100 个标的
WebSocket 连接管理:
- 心跳检测:客户端每 25 秒发送 ping,服务端 60 秒无响应则断开
- 单服务器并发上限:根据内存评估,通常每万连接占用 1-2GB RAM
- 消息队列深度:客户端离线时最多缓存 50 条消息
数据源配额管理:
- 为每个 API Key 维护独立计数器
- 达到配额 80% 时触发降级策略(延长轮询间隔)
- 实现熔断机制:连续错误超过阈值后暂停请求 5 分钟
告警系统阈值:
- 单用户最大活跃规则数:100 条
- 全局规则匹配 QPS:根据数据频率设计,通常 10K-50K/s
- 通知冷却期:300 秒
监控指标:
- 数据延迟:从源到客户端的端到端 P99 延迟应小于 500ms
- 连接健康度:SSE 自动重连率、WebSocket 异常断开率
- 告警准确率:误报率控制在 1% 以下
OpenStock 的开源模式证明了高质量金融数据服务不必依赖昂贵的商业授权。通过合理的技术选型和严格的工程实现,完全可以在免费数据源的基础上构建出延迟可控、功能完整的实时行情平台。对于希望自建系统的团队,建议从 SSE 行情推送起步,逐步叠加 WebSocket 交互功能和告警引擎,避免一次性引入过多复杂度。
资料来源:
- OpenStock GitHub 仓库
- SSE vs WebSockets: Choosing the Right Tool for Stock Market Applications
- Build a Real-Time Stock App with React and Hono
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。