前端的全栈混合之路Meteor篇:分布式数据协议DDP深度剖析

本文属于进阶篇,并不是太适合新人阅读,但纯粹的学习还是可以的,因为后续会实现很多个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进行序列化和反序列,从而支持了更多的对象传输,详参考 前端的全栈混合之路Meteor篇(四):支持自定义对象序列化的EJSON介绍
  3. 发布/订阅模型 : 允许客户端订阅服务器端的数据集,并在数据变化时接收更新。它的应用例子见文章 前端的混合全栈之路Meteor篇(三):发布订阅示例代码及如何将Meteor的响应数据映射到vue3的reactive系统
  4. 方法调用 : 客户端可以调用服务器端的方法,实现远程过程调用(RPC)。基于它的应用例子见文章 前端的全栈混合之路Meteor篇(二):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: 客户端发起连接请求

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

    json 复制代码
    {"msg": "connected", "session": "RandomSessionId123"}
  3. ping/pong: 心跳消息

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

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

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

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

    json 复制代码
    {"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

时序图预览

DDP在Meteor中的应用

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

总结

DDP协议是Meteor框架的核心组件之一,它为实时Web应用提供了强大而灵活的数据同步机制。通过使用DDP,开发者可以轻松构建响应迅速、实时更新的现代Web应用,同时保持了在不同网络环境下的适应性。

相关推荐
初遇你时动了情31 分钟前
uniapp 城市选择插件
开发语言·javascript·uni-app
zhangjr05751 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
zongzi_4941 小时前
二次封装的天气时间日历选择组件
开发语言·javascript·ecmascript
木子七2 小时前
vue2-vuex
前端·vue
麻辣_水煮鱼2 小时前
vue数据变化但页面不变
前端·javascript·vue.js
BY—-组态2 小时前
web组态软件
前端·物联网·工业互联网·web组态·组态
一条晒干的咸魚2 小时前
【Web前端】实现基于 Promise 的 API:alarm API
开发语言·前端·javascript·api·promise
天冬忘忧2 小时前
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化
大数据·分布式·kafka
WilliamLuo2 小时前
MP4结构初识-第一篇
前端·javascript·音视频开发