返回文章列表

文章

一个进程里该有几个Endpoint?什么时候共享,什么时候隔离?

目录
  1. 一、先给出结论
  2. 二、为什么「一个 Endpoint」通常是正确答案?
  3. Endpoint 的本质再强调一次
  4. Endpoint 内部已经能做的事(很多人低估了)
  5. 三、什么时候「共享 Endpoint」是正确的?
  6. ✅ 场景 1:同一个应用 / 同一个身份
  7. ✅ 场景 2:库 + 上层应用
  8. 这是非常“工业级”的设计。
  9. 四、什么时候「必须拆成多个 Endpoint」?
  10. ❌ 错误理由(很多人会犯)
  11. ✅ 正确理由 1:身份不同
  12. ✅ 正确理由 2:安全 / 信任域隔离
  13. ✅ 正确理由 3:网络策略根本不同
  14. 五、一个非常重要但容易忽略的点
  15. Endpoint ≠ Session ≠ Connection
  16. 六、结合你现在的 sendme / iroh 场景
  17. 你的真实需求是:
  18. 所以你的设计应该是:
  19. 七、一句「工程级」总结

一、先给出结论#

绝大多数情况下:一个进程只需要一个 Endpoint。 只有当“身份 / 网络语义不同”时,才应该拆分多个 Endpoint。 记住这句话,后面所有内容都是在解释它。


二、为什么「一个 Endpoint」通常是正确答案?#

Endpoint 的本质再强调一次#

Endpoint = 节点在网络中的“身份 + 可达性 + 连接管理器” 它不是:

  • 一个 socket
  • 一个连接
  • 一个请求上下文 而是:

“我这个进程,在整个网络中的存在方式”


Endpoint 内部已经能做的事(很多人低估了)#

一个 Endpoint 内部就已经支持:

  • 多个并发连接
  • 同时 serve + connect
  • 多路复用(QUIC stream)
  • 自动 NAT 路径切换
  • 多 peer 并存 👉 你几乎不可能因为“不够用”而需要第二个 Endpoint

三、什么时候「共享 Endpoint」是正确的?#

✅ 场景 1:同一个应用 / 同一个身份#

Tauri App
 ├── 文件发送
 ├── 文件接收
 ├── 状态同步
 └── 控制指令

一个 Endpoint 原因:

  • 同一 NodeId
  • 同一网络策略
  • 共享 NAT 映射 / Relay
  • 连接可复用(省资源、提速)

✅ 场景 2:库 + 上层应用#

比如你现在做的:

sendme (library)
     ↑
tauri app

Endpoint 由上层创建,传入库中使用

pub struct SendService {
    endpoint: Endpoint,
}

这是非常“工业级”的设计。#

四、什么时候「必须拆成多个 Endpoint」?#

这是重点。

❌ 错误理由(很多人会犯)#

  • “功能不同”
  • “模块不同”
  • “代码想解耦” 这些都不是理由。

✅ 正确理由 1:身份不同#

如果你需要:

  • 同一进程
  • 多个“逻辑节点”
  • 在网络中表现为不同的人
一个进程 = 模拟多个独立节点

那么: ✔ 每个身份 = 一个 Endpoint 典型场景:

  • P2P 测试工具
  • 节点模拟器
  • 多账号系统

✅ 正确理由 2:安全 / 信任域隔离#

例如:

  • 一个 Endpoint 用于公网
  • 一个 Endpoint 用于内网
  • 一个 Endpoint 只用于匿名通信 因为 Endpoint 内部共享:
  • 私钥
  • 中继关系
  • 已建立的连接 👉 如果这些不能共享,就必须拆。

✅ 正确理由 3:网络策略根本不同#

比如:

  • 一个 Endpoint 禁用 relay
  • 一个 Endpoint 强制走 relay
  • 一个只监听内网 这已经是不同网络实体了。

五、一个非常重要但容易忽略的点#

Endpoint ≠ Session ≠ Connection#

很多人潜意识是:

一次 send → 一个 endpoint

这是 完全错误的直觉(但很常见)。 正确的层级是:

Endpoint
 └── Connection (peer)
      └── Stream (task / request)

你应该:

  • 长期持有 Endpoint
  • 短期创建 Connection
  • 极短期使用 Stream

六、结合你现在的 sendme / iroh 场景#

你的真实需求是:#

  • 一个 Tauri App
  • 扮演一个 P2P 节点
  • 多次发送 / 接收
  • GUI 生命周期长

所以你的设计应该是:#

App 启动
 └── 创建 Endpoint(一次)
     ├── send()
     ├── receive()
     ├── show_progress()
     └── background tasks

❌ 不要:

  • 每次 send 新建 Endpoint
  • 每次 receive 新建 Endpoint 这会导致:
  • NAT 映射反复重建
  • Relay 重复注册
  • ticket 行为变得“看似诡异”

七、一句「工程级」总结#

Endpoint 是“节点级”的对象,不是“操作级”的对象。 或者用更狠的话说: 你创建 Endpoint 的次数,应该和你在现实世界中“创建新身份”的次数一样少。