前端的全栈之路Meteor篇(七):轻量的NoSql分布式数据协议同步协议DDP深度剖析

简介: 本文深入探讨了DDP(Distributed Data Protocol)协议,这是一种在Meteor框架中广泛使用的发布/订阅协议,支持实时数据同步。文章详细介绍了DDP的主要特点、消息类型、协议流程及其在Meteor中的应用,包括实时数据同步、用户界面响应、分布式计算、多客户端协作和离线支持等。通过学习DDP,开发者可以构建响应迅速、适应性强的现代Web应用。

本文属于进阶篇,并不是太适合新人阅读,但纯粹的学习还是可以的,因为后续会实现很多个ddp的版本用于web端、nodejs端、安卓端和ios端,提前预习和复习下。ddp协议是一个C/S架构的协议,但是客户端也同时可以是服务端。

什么是DDP?

DDP (Distributed Data Protocol) 是Meteor框架中使用的一种简单而强大的发布/订阅协议。它允许客户端和服务器之间进行实时数据同步,是Meteor实现实时应用的核心技术之一。

DDP的主要特点

  1. 传输层灵活性: DDP可以基于WebSocket,也可以通过HTTP长轮询等方式实现,例如使用SockJS在不支持WebSocket的环境中工作。
  2. JSON格式: 所有的消息都使用JSON格式,便于解析和调试。-需要注意的是,实际的传输是用的EJSON进行序列化和反序列,从而支持了更多的对象传输,详参考 支持自定义对象序列化的EJSON介绍
  3. 发布/订阅模型: 允许客户端订阅服务器端的数据集,并在数据变化时接收更新。
  4. 方法调用: 客户端可以调用服务器端的方法,实现远程过程调用(RPC)。基于它的应用例子见文章 RPC方法注册及调用
  5. 实时更新: 当订阅的数据发生变化时,服务器会自动将更新推送给客户端。这部分是和发布订阅关联的,本文会涉及到底层实现
  6. 会话管理: 使用会话ID来维护客户端和服务器之间的连接状态。

DDP协议的详细过程

1. 握手和连接建立

  1. 客户端发送 connect 消息,可能包含版本信息和会话ID(如果是重连)。
  2. 服务器回复 connected 消息,包含新的会话ID。
  3. 如果是重连,服务器会恢复之前的订阅和方法调用状态。

2. 保活和心跳机制

  1. 客户端定期(通常每45秒)发送 ping 消息。
  2. 服务器回复 pong 消息。
  3. 如果超时未收到 pong,客户端可能会尝试重新连接。

3. 方法调用

  1. 客户端发送 method 消息,包含方法名和参数。
  2. 服务器执行方法,可能会触发数据变更。
  3. 服务器发送 result 消息,包含方法执行结果或错误信息。
  4. 如果方法导致数据变更,服务器会发送相应的 addedchangedremoved 消息。

4. 发布和订阅

  1. 客户端发送 sub 消息,包含订阅名称和参数。
  2. 服务器开始发送相关数据:
    • added 消息用于新增的文档
    • changed 消息用于更新的文档
    • removed 消息用于删除的文档
  3. 服务器发送 ready 消息,表示初始数据集已发送完毕。
  4. 之后,服务器会持续发送 addedchangedremoved 消息以保持数据同步。
  5. 客户端可以发送 unsub 消息来取消订阅。

DDP消息类型详解

  1. connect: 客户端发起连接请求

    {
         "msg": "connect", "version": "1", "support": ["1", "pre2", "pre1"]}
    
  2. connected: 服务器确认连接成功

    {
         "msg": "connected", "session": "RandomSessionId123"}
    
  3. ping/pong: 心跳消息

    {
         "msg": "ping", "id": "unique-id-123"}
    {
         "msg": "pong", "id": "unique-id-123"}
    
  4. sub/unsub: 订阅和取消订阅

    {
         "msg": "sub", "id": "random-id", "name": "publicationName", "params": []}
    {
         "msg": "unsub", "id": "random-id"}
    
  5. added/changed/removed: 数据更新通知

    {
         "msg": "added", "collection": "collectionName", "id": "documentId", "fields": {
         }}
    {
         "msg": "changed", "collection": "collectionName", "id": "documentId", "fields": {
         }}
    {
         "msg": "removed", "collection": "collectionName", "id": "documentId"}
    
  6. ready: 初始数据加载完成通知

    {
         "msg": "ready", "subs": ["subscription-id-1", "subscription-id-2"]}
    
  7. method/result: 方法调用和结果

    {
         "msg": "method", "method": "methodName", "params": [], "id": "call-id"}
    {
         "msg": "result", "id": "call-id", "result": {
         } }
    

    DDP全生命周期时序图

    可使用mermaid进行预览,时序图code如下

    sequenceDiagram
     participant Client
     participant Server
    
     %% 握手和连接建立
     Client->>Server: connect {version: "1", support: ["1", "pre2", "pre1"]}
     Server-->>Client: connected {session: "RandomSessionId123"}
    
     %% 发布订阅
     Client->>Server: sub {id: "sub1", name: "posts", params: []}
     Server-->>Client: added {collection: "posts", id: "post1", fields: {...}}
     Server-->>Client: added {collection: "posts", id: "post2", fields: {...}}
     Server-->>Client: ready {subs: ["sub1"]}
    
     %% 实时更新
     loop Real-time updates
         Server-->>Client: changed {collection: "posts", id: "post1", fields: {...}}
         Server-->>Client: added {collection: "posts", id: "post3", fields: {...}}
         Server-->>Client: removed {collection: "posts", id: "post2"}
     end
    
     %% 方法调用
     Client->>Server: method {method: "addPost", params: [...], id: "m1"}
     Server-->>Client: added {collection: "posts", id: "post4", fields: {...}}
     Server-->>Client: result {id: "m1", result: {...}}
    
     %% 取消订阅
     Client->>Server: unsub {id: "sub1"}
    
     %% 心跳机制
     loop Keep-alive
         Client->>Server: ping {id: "ping1"}
         Server-->>Client: pong {id: "ping1"}
     end
    

    时序图预览
    dfa4203e03da4af58a767a375bf41461.png

DDP在Meteor中的应用

  1. 实时数据同步: 当服务器端的数据发生变化时,客户端可以立即收到更新。
  2. 用户界面响应: 通过DDP,用户界面可以实时反映数据的变化,提供流畅的用户体验。
  3. 分布式计算: 客户端可以调用服务器端的方法,实现复杂的计算或数据处理。
  4. 多客户端协作: 多个客户端可以同时订阅相同的数据集,实现实时协作功能。
  5. 离线支持: 通过本地缓存和重连机制,DDP可以支持离线操作和数据同步。

总结

DDP协议为实时Web应用提供了强大而灵活的数据同步机制,通过使用DDP,开发者可以轻松构建响应迅速、实时更新的现代Web应用,同时保持了在不同网络环境下的适应性。利用ddp开发一个后端作为转发中心,就可以实现多端+数据库之间的数据同步。

相关文章
|
10月前
|
消息中间件 分布式计算 资源调度
《聊聊分布式》ZooKeeper与ZAB协议:分布式协调的核心引擎
ZooKeeper是一个开源的分布式协调服务,基于ZAB协议实现数据一致性,提供分布式锁、配置管理、领导者选举等核心功能,具有高可用、强一致和简单易用的特点,广泛应用于Kafka、Hadoop等大型分布式系统中。
|
10月前
|
机器学习/深度学习 监控 PyTorch
68_分布式训练技术:DDP与Horovod
随着大型语言模型(LLM)规模的不断扩大,从早期的BERT(数亿参数)到如今的GPT-4(万亿级参数),单卡训练已经成为不可能完成的任务。分布式训练技术应运而生,成为大模型开发的核心基础设施。2025年,分布式训练技术已经发展到相当成熟的阶段,各种优化策略和框架不断涌现,为大模型训练提供了强大的支持。
1127 0
|
Cloud Native 前端开发 JavaScript
前端开发者必看:不懂云原生你就OUT了!揭秘如何用云原生技术提升项目部署与全栈能力
【10月更文挑战第23天】随着云计算的发展,云原生逐渐成为技术热点。前端开发者了解云原生有助于提升部署与运维效率、实现微服务化、掌握全栈开发能力和利用丰富技术生态。本文通过示例代码介绍云原生在前端项目中的应用,帮助开发者更好地理解其重要性。
522 0
|
JavaScript 前端开发 Docker
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
在使用 Deno 构建项目时,生成的可执行文件体积较大,通常接近 100 MB,而 Node.js 构建的项目体积则要小得多。这是由于 Deno 包含了完整的 V8 引擎和运行时,使其能够在目标设备上独立运行,无需额外安装依赖。尽管体积较大,但 Deno 提供了更好的安全性和部署便利性。通过裁剪功能、使用压缩工具等方法,可以优化可执行文件的体积。
1371 3
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
|
JavaScript 前端开发 测试技术
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
1106 7
|
前端开发 JavaScript 中间件
前端全栈之路Deno篇(四):Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
Deno 是由 Node.js 创始人 Ryan Dahl 开发的新一代 JavaScript 和 TypeScript 运行时,旨在解决 Node.js 的设计缺陷,具备更强的安全性和内置的 TypeScript 支持。本文介绍了如何使用 Deno 内置的 `Deno.serve` 快速创建 HTTP 服务,并详细讲解了 Oak 框架的安装和使用方法,包括中间件、路由和静态文件服务等功能。Deno 和 Oak 的结合使得创建 RESTful API 变得高效且简便,非常适合快速开发和部署现代 Web 应用程序。
808 2
|
JavaScript 前端开发 Serverless
前端全栈之路Deno篇:Deno2.0与Bun对比,谁更胜一筹?可能Deno目前更适合serverless业务
在前端全栈开发中,Deno 2.0 和 Bun 作为新兴的 JavaScript 运行时,各自展现了不同的优势。Deno 2.0 重视安全性和多平台兼容性,尤其是对 Windows 的良好支持和原生 TypeScript 支持;而 Bun 则以卓越的性能和简便的开发体验著称,适合快速迭代的小型项目。两者在不同场景下各具特色,Deno 更适合企业级应用和serverless,Bun 则适用于追求速度的项目。
2613 2
|
前端开发 安全 API
前端全栈之路Deno篇(三):一次性搞懂和学会用Deno 2.0 的权限系统详解和多种权限配置权限声明方式
本文深入解析了 Deno 2.0 的权限系统,涵盖主包和第三方包的权限控制机制,探讨了通过命令行参数、权限 API 和配置文件等多种权限授予方式,并提供了代码示例和运行指导,帮助开发者有效管理权限,提升应用安全性。
585 0
|
12月前
|
存储 负载均衡 NoSQL
【赵渝强老师】Redis Cluster分布式集群
Redis Cluster是Redis的分布式存储解决方案,通过哈希槽(slot)实现数据分片,支持水平扩展,具备高可用性和负载均衡能力,适用于大规模数据场景。
782 2
|
12月前
|
存储 缓存 NoSQL
【📕分布式锁通关指南 12】源码剖析redisson如何利用Redis数据结构实现Semaphore和CountDownLatch
本文解析 Redisson 如何通过 Redis 实现分布式信号量(RSemaphore)与倒数闩(RCountDownLatch),利用 Lua 脚本与原子操作保障分布式环境下的同步控制,帮助开发者更好地理解其原理与应用。
836 6