
今日三荐:数据流、云上搜索与 NAT 穿透
从 Dora、Quickwit 和 rathole 出发,分别练习实时数据流、云存储搜索与 NAT 穿透,并给出能在今晚跑通的最小路径。
今天可以沿着一条很具体的学习线来选项目:数据如何穿过工程边界。Dora 把数据放进有向图,在节点之间传递;Quickwit 把索引计算和云对象存储拆开;rathole 则把 NAT 后面的本地服务接到公网入口。
这三个项目的共同点不是都使用 Rust,而是都把「一个程序怎样和外部世界交换数据」写成了可以观察的机制。你可以先跑最小例子,再顺着数据流去读源码。
1. Dora:先看一条数据流怎样被拆成节点
仓库:dora-rs/dora · Rust 核心,支持 Python、C、C++ 节点
Dora 是面向机器人和 AI 实时应用的数据流框架。开发者用 YAML 描述有向图,把发送、转换、接收等步骤拆成节点;每个节点可以用不同语言编写,Apache Arrow 负责数据表示,Zenoh 负责节点之间的通信。Dora 还提供录制回放、运行时监控、故障重启和跨机器部署能力。1
这套结构适合本科生学习,因为它把「分布式系统」缩成了一张可以追踪的图。CLI 负责启动和管理数据流,Coordinator 负责编排生命周期,每台机器上的 Daemon 负责启动节点;本地小实验可以先绕开分布式控制面,直接运行一个数据流。1
最值得拆的机制
- YAML 中的输入和输出怎样变成节点之间的边。
- Arrow 数组怎样从发送节点传到接收节点。
- 本机的大消息为什么可以走 Zenoh 共享内存,跨机器时又回到网络传输。
- 同一条数据流怎样混合 Python 和 Rust,而不把每个节点绑死在同一种语言上。
复现难度:中。Python 路径要求 Python 3.11 或更高版本;安装 Python API 时,包名是
dora-rs,代码里的导入名仍然是 dora。这个命名差异很容易让第一次安装的人误装同名包。1先准备 CLI 和 Python 依赖:
cargo install dora-cli
python -m pip install dora-rs numpy pyarrow再运行仓库自带的 Python 数据流:
git clone https://github.com/dora-rs/dora.git
cd dora
dora run examples/python-dataflow/dataflow.yml这个例子可以先当作
sender → transformer → receiver 三段链路来观察。你可以打开 dataflow.yml,找出每个节点的输入输出;然后进入发送节点,观察 node.send_output 如何把一个 Arrow 数组交给下一步。1今晚可以做的最小练习:把 transformer 改成一个带计数器的节点,让它给每条消息增加序号,再在 receiver 端打印原值和新值。你要记录的不是最终输出,而是消息经过哪一个端口、由哪一种语言处理,以及停止信号怎样让节点退出。
Dora 被纳入今天这一期,还有一个明确的维护理由:仓库页面显示 2026 年 8 月 21 日 仍有提交;同一天的提交记录里还出现了跨机器节点连接、显式 daemon 管理和 Python CUDA 辅助代码等改动。23
边界也要一起看:Dora 提供的是软实时能力,ROS2 桥接仍属于实验性支持;Coordinator 重启后的运行中数据流接管也还不完整。Linux 上的 Rust/Python 路径最适合第一次复现,Windows、WSL 以及 C/C++ 组合需要额外验证。1
2. Quickwit:把日志搜索拆成索引、存储与查询
仓库:quickwit-oss/quickwit · Rust
Quickwit 是面向日志和分布式追踪的云原生搜索引擎。它把索引数据放在 S3、Azure Blob Storage 或 Google Cloud Storage 等对象存储中,让无状态的索引器和搜索器分别承担写入与查询;项目还提供全文检索、聚合、REST API、OpenTelemetry 和 Jaeger 接入。4
它最适合用来学习「搜索系统为什么要做架构取舍」。你不需要一开始就读完整的倒排索引实现,只要追一份 JSON 的路径:文档先按 schema 建立索引,再写入对象存储,搜索器读取索引并返回结果。计算与存储分离以后,扩容、数据保留和故障恢复都会变成独立问题。
最值得拆的机制
- schema 怎样决定哪些字段被分词、索引、存储或聚合。
- 索引器和搜索器为什么可以设计成无状态组件。
- Elasticsearch/OpenSearch 兼容 API 怎样降低迁移成本,又为什么仍然不等于完整兼容。
- 日志、trace 和 metrics 进入系统时,数据模型为什么不能混为一谈。
复现难度:中。Quickwit 官方 Quickstart 当前展示的是
0.9.0,同时提供安装脚本和 Docker 镜像。第一次尝试更建议使用 Docker,把数据目录挂载到本地;这样你可以先观察 HTTP API 和索引目录,再决定是否从源码编译。5启动本地服务:
mkdir -p qwdata
docker run --rm \
-v "$(pwd)/qwdata:/quickwit/qwdata" \
-p 127.0.0.1:7280:7280 \
quickwit/quickwit:0.9.0 run另开一个终端,先确认服务能响应:
curl http://localhost:7280/api/v1/versionQuickwit 的教程使用 Stack Overflow 帖子建立第一个索引。你可以直接取官方 schema 和 10,000 条 NDJSON 数据,再通过 REST API 建索引、导入数据和查询:
curl -o stackoverflow-index-config.yaml \
https://raw.githubusercontent.com/quickwit-oss/quickwit/v0.9.0/config/tutorials/stackoverflow/index-config.yaml
curl -XPOST http://127.0.0.1:7280/api/v1/indexes \
--header "content-type: application/yaml" \
--data-binary @stackoverflow-index-config.yaml
curl -O https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json
curl -XPOST "http://127.0.0.1:7280/api/v1/stackoverflow/ingest?commit=force" \
--data-binary @stackoverflow.posts.transformed-10000.json
curl "http://127.0.0.1:7280/api/v1/stackoverflow/search?query=search+AND+engine"这些命令把「配置 schema → 创建索引 → 导入文档 → 发起查询」连成了一条可观察的路径。你可以把
title:search AND engine 换成字段查询,再试一次聚合请求,看看查询 DSL 怎样改变返回结果。5今晚可以做的最小练习:只改 schema 里的一个字段设置,例如让
title 成为默认搜索字段,再比较普通查询和字段限定查询的结果。然后删除索引,重建一个只保留少量文档的版本。这个过程会让你看到 schema、数据目录和查询 API 之间的对应关系。Quickwit 的当前维护信号很清楚:仓库页面显示 2026 年 8 月 20 日 的最新提交,主题是过滤带前缀列表中的词法同级项;项目页面还展示了 CI、Codecov 和 OpenSSF Scorecard 等工程信号。6
它的限制同样适合放进学习笔记:metrics 仍在路线图中,索引服务的高可用依赖 Kafka 数据源,Elasticsearch/OpenSearch 也只兼容其中较大一部分 API。你可以把这次本地实验当成搜索系统入门,不能直接把它当成生产集群的容量或高可用验证。4
3. rathole:用两份配置看懂 NAT 穿透
仓库:rathole-org/rathole · Rust
rathole 是一个用于 NAT 穿透的反向代理。它让公网服务器作为入口,把 NAT 后设备上的本地服务转发出来;客户端主动连接服务器,服务端再把公网端口映射到客户端指定的本地地址。项目支持 TCP 和 UDP 服务、Token 认证,以及 TLS 或 Noise 加密传输。7
这个项目的学习价值在于,网络拓扑可以被压缩成两份 TOML。服务端只需要知道监听地址和对外暴露端口,客户端只需要知道远程地址和本地服务地址;两边通过同名服务和同一个 Token 配对。
最值得拆的机制
- 为什么 NAT 后的客户端需要主动向公网服务器建立连接。
remote_addr、local_addr和bind_addr各自处在网络路径的哪一端。- Token 认证解决了服务配对问题,TLS/Noise 又分别解决了什么问题。
- TCP_NODELAY、心跳和端口暴露怎样影响交互延迟与安全边界。
复现难度:低到中。你需要一台能监听公网端口的服务器,以及另一台能访问本地服务的设备。第一次实验可以不碰真实 NAS 或 SSH,而是在客户端启动一个只监听本机的 HTTP 服务,再通过公网端口访问它。项目提供 Release 二进制、Docker 镜像和源码构建路径;先用预编译文件更省时间。7
服务端配置
server.toml:[server]
bind_addr = "0.0.0.0:2333"
[server.services.demo]
token = "use_a_secret_that_only_you_know"
bind_addr = "0.0.0.0:5202"客户端配置
client.toml:[client]
remote_addr = "myserver.com:2333"
[client.services.demo]
token = "use_a_secret_that_only_you_know"
local_addr = "127.0.0.1:8000"分别启动两端:
./rathole server.toml
./rathole client.toml如果客户端本地的 HTTP 服务监听
127.0.0.1:8000,访问公网服务器的 5202 端口,就会沿着「公网端口 → rathole 服务端 → 长连接 → 客户端本地服务」这条路径转发。配置中的服务名和 Token 必须一致,服务器防火墙也必须放行 rathole 端口与对外服务端口。7今晚可以做的最小练习:先把
local_addr 指向一个本地静态文件服务器,再故意改错 Token、服务名和公网端口,分别记录客户端与服务端的报错。你会比只读「NAT 穿透」四个字更快理解连接建立、认证和转发是三件不同的事。rathole 的维护边界需要说清楚:仓库页面显示最新提交是 2025 年 7 月 29 日,最新正式版本
v0.5.0 发布于 2023 年 10 月 1 日;项目仍有源码和测试目录的后续提交,但版本发布节奏明显慢于代码提交。它适合学习一条短小的网络代理主线,生产部署前要自己核对版本、加密配置和暴露端口。8怎么选今晚动手的那一个
| 你现在的状态 | 更建议先碰 | 先学哪条主线 | 最小条件与关键限制 |
|---|---|---|---|
| 想先理解多语言节点怎样组成一条实时管线 | Dora | YAML 数据流、Arrow 消息、节点生命周期 | Python 路径要求 3.11+;Linux 的 Rust/Python 组合最省事,软实时与 Coordinator 恢复能力要单独验证。1 |
| 想把日志、schema、索引和查询串起来 | Quickwit | schema、索引写入、REST 查询、计算与存储分离 | Docker 最容易起步;教程会下载 10,000 条 Stack Overflow 数据,metrics 和部分高可用能力仍有限。45 |
| 想用最少代码看懂网络边界 | rathole | NAT 穿透、服务映射、认证与加密 | 需要公网服务器、可访问的本地服务和开放端口;版本发布较慢,真实部署不能省略安全配置。78 |
如果你只有一台电脑,先选 Dora,因为仓库自带的 Python 数据流可以直接展示节点边界。你已经有 Docker 和一点日志数据,就选 Quickwit,把 schema 和查询结果一起记下来。你手头有云服务器,或者想把计算机网络课里的 NAT 变成可访问的实验,再选 rathole。
这三条路线分别对应三种读源码的方法:先看图上的数据边,先看索引和查询的落点,先看一条连接怎样穿过网络。今晚只完成一条最小路径,明天再沿着一个中间对象继续追,比同时打开三个仓库更容易留下真正的理解。
References
- 1Dora README
github.com
- 2Dora 最新提交
github.com
- 3Dora 跨机器链路提交
github.com
- 4Quickwit README
github.com
- 5Quickwit Quickstart
quickwit.io
- 6Quickwit 最新提交
github.com
- 7rathole README
github.com
- 8rathole 当前仓库状态
github.com
This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.
