返回 BIM 与 IFC 博客
每个动态数据源都标榜自己“实时”。对数字孪生来说,这个词掩盖了唯一一个决定其颜色含义的数字:数据到达时已经有多旧。停车桩因为三分钟前没有单车而被涂成红色,和它此刻确实没有单车,并不是一回事。
于是我们做了测量。我们连续 24 小时记录了巴塞罗那、赫尔辛基和东京的实时孪生所读取的六个公开数据源,并针对每次响应中的每一辆车、每一个站点,比较发布方写入的时间与数据到达的时间。完整记录已公开[log]。
要点
- HSL 的 MQTT 数据流不到 1 秒即到达。同一车队的 GTFS-Realtime 数据滞后约 2 秒,但浏览器无法读取这个数据源。
- 都营列车的位置滞后约半分钟。都营公交的位置和 Bicing 站点的中位滞后约一分半钟,其中 90% 在约三分钟以内。
- 数据源自身的时间戳可能误导人:Bicing 文件只“旧”了三分之一秒,而其中的站点大约在 95 秒前就已报告。
- Endolla 的充电桩数据源完全没有报告时间,只有每个充电桩最后一次状态变化的时间,因此无法显示数据有多新。
- 全部 14,329 次请求都得到了响应,MQTT 数据流在一天中的每一分钟都有消息。
典型响应中车辆或站点的中位滞后,以及其中 90% 的滞后上限。
测量方法
- 从 2026 年 10 月 15 日 21:15 UTC 到 10 月 16 日 21:15 UTC,在欧洲一台时钟已同步的计算机上进行。
- HSL GTFS-Realtime 每 15 秒轮询一次;Bicing 和两个都营数据源每 30 秒一次;Endolla 每 5 分钟一次。HSL 的 MQTT 数据流订阅了赫尔辛基地区,并按分钟汇总。
- 对每次响应,我们取其中车辆或站点滞后的中位数和第 90 百分位数;图中显示的是这两项在 24 小时内的典型值。
滞后是到达时间减去发布方为每个条目写入的时间戳:在 GTFS-Realtime[gtfsrt] 中,是测得车辆位置的时刻;在 GBFS[gbfs] 中,是站点最后一次报告的时间;在 HSL 的数据流[hfp]中,是每条消息自身的时间;在 ODPT 中,是每列列车的记录时间。
各数据源的结果
| 数据源 | 传输方式 | 中位滞后 | 90% 的条目低于 | 每次响应的条目数 |
|---|
| HSL 公交,HFP(赫尔辛基) | MQTT,推送 | 不到 1 秒 | 不到 1 秒 | 每分钟约 28,000 条消息 |
| HSL 车辆,GTFS-Realtime(赫尔辛基) | HTTP,每 15 秒;无 CORS | 1.9 秒 | 1.9 秒 | 843 辆车 |
| 都营列车,ODPT(东京) | HTTP,每 30 秒 | 28 秒 | 30 秒 | 92 列列车 |
| 都营公交,GTFS-Realtime(东京) | HTTP,每 30 秒 | 88 秒 | 3.1 分钟 | 490 辆公交车 |
| Bicing 站点,GBFS 3.0(巴塞罗那) | HTTP,每 30 秒 | 95 秒 | 2.8 分钟 | 543 个站点 |
| Endolla 充电桩,GELFS(巴塞罗那) | HTTP,每 5 分钟 | 未提供 | 未提供 | 1,366 个充电接口 |
2026 年 10 月 15–16 日 24 小时内的典型值。条目数为中位数;都营在凌晨时段没有列车和公交运行。
结果分成三组。HSL 在每辆公交车上报的同时就把数据发布出去,因此通过 MQTT 的滞后接近于零,通过批量生成的 GTFS-Realtime 文件则约为两秒。都营的列车记录通常滞后约半分钟。都营公交和 Bicing 站点各自每隔几分钟才报告一次,所以在任一时刻,都有大约一半的滞后超过一分半钟:49% 的公交车和 52% 的站点滞后超过 90 秒。
自称“新鲜”的时间戳
Bicing 的站点状态文件带有一个 last_updated 时间,它与当前时间的差距始终不到 1 秒:文件是在响应请求时才打上时间戳的。而其中 543 个站点的报告时间,中位数是 95 秒之前。信任文件时间的孪生,会在一分半钟前的数据上显示“0 秒前更新”。都营公交数据源也有同样的情况,只是程度较轻:文件时间戳滞后约 16 秒,其中的公交车约 88 秒。
道理很简单:滞后是每个条目的属性,而不是文件的属性。读取每辆车或每个站点自己报告的时间,并把它显示出来。
无从判断的数据源
在 286 个五分钟间隔中,Endolla 充电点文件的大小有 262 次发生了变化,可见它确实有人在维护。但每个充电接口只带有其状态最后一次变化的时间:一半的接口约 21 小时没有变化,十分之一超过 10 天。这可能完全准确,只是充电桩整夜没人使用;也可能是充电桩已经停止报告,而数据源无法区分这两种情况。孪生可以把这类数据显示为“按发布原样”,但绝不能显示为实时数据。
推送与轮询
HSL 的两个渠道传送的是同一批公交车。通过 MQTT,每个位置一产生就送达;通过轮询的文件,它要等下一个批次,浏览器还要在此基础上再等下一次轮询。轮询也有成本:Bicing 文件包含全部 543 个站点,压缩前约 268 KB,因此即使孪生只需要一个站点,每次轮询仍要把所有站点都下载下来。轮询频率高于数据源的更新频率,只会把这份带宽白白多花一遍。
这对孪生意味着什么
- 在数值旁边显示滞后时间,依据条目自身的时间戳,而不是文件的时间戳。
- 把过期阈值设在数据源的正常滞后之上。本文的实时案例中,HSL 停靠位用 45 秒,都营列车用 2 分钟,都营公交站用 10 分钟,Bicing 用 15 分钟。
- 灰色表示“没有最新数据”,绝不能把上一个值伪装成当前值。
- 发布方提供推送时,优先使用推送;轮询频率不要高于数据源的更新频率。
- 没有逐条时间的数据源可以显示,但不能称为实时。
网页究竟能否读取这些数据源,是问题的另一半,见网页能读取哪些城市开放数据。赫尔辛基孪生如何使用 MQTT 数据流,见基于 MQTT 的公交总站孪生。
参考文献
- 24 小时记录(CSV) — IFC Viewer Online. 每个数据源的每一次轮询(以及 MQTT 数据流的每一分钟),附其中车辆或站点的滞后分布。2026 年 10 月 15–16 日。
- GTFS Realtime 参考文档 — MobilityData. VehiclePosition.timestamp:测得车辆位置的时刻。
- 通用共享单车数据规范(GBFS) — MobilityData. last_reported:站点最后一次向运营方后台报告状态的时间。
- 高频定位(HFP) — Digitransit / HSL. HSL 通过 MQTT 发布的车辆位置,每条消息都带有时间戳。
城市实时数据到底有多新?6 个数据源连续 24 小时实测