客户端工作原理
不管是命令行客户端还是 SDK 客户端,做的都是同样三件事:和 orbitproxy 云网关建立会话,在会话上承载端点,再把流量送回你的上游服务。这三件事基本解释了客户端的全部行为,包括那些容易让人意外的部分。
会话
客户端启动后,会主动连接 orbitproxy 云网关,建立一条长期保持的 TLS 加密连接。这条连接就是会话,也是控制中心里判断一个客户端是否在线的依据。
建立会话
建立会话分三步:
- 客户端出站连接云网关地址,完成 TLS 握手。握手时它会用注册时下发的 CA 证书校验云网关的证书,校验不通过就不会继续。
- 客户端发送一条用本机私钥签名的握手消息,里面带着自己的 Machine Key 和客户端版本。云网关用注册时保存的公钥验证签名,确认这个客户端确实是它声称的那一个。
- 验证通过后,云网关返回会话 ID,会话建立完成。之后云网关下发的指令、客户端上报的状态,都在这条会话上往返。
会话只有出站方向,你的机器上没有任何监听入站连接的端口。所以它可以在 NAT、公司防火墙和你无法控制的网络里工作,也不需要做端口映射或者添加入站防火墙规则。
会话是你管理客户端的把手
因为云网关持有会话的另一端,所以你可以在控制中心里管理一个客户端,即使你当时没有办法登录那台机器:
- 停止。 客户端回复确认之后断开会话,并且不再自动重连。
- 重启。 客户端回复确认之后,在原地重启自己,沿用原来的启动参数。
- 升级。 客户端下载新版本替换自身,再重启。下载或安装失败时,会把失败原因回报给云网关。
保活与重连
客户端每 30 秒发送一次保活消息检查连接是否可用。网络中断、Wi-Fi 切换到移动网络、笔记本休眠唤醒之后,客户端会发现连接已经失效并自动重连。
重连会重新走一遍完整的建立过程,重试间隔逐渐拉长:
- 客户端刚启动、第一次还没连上时,会一直重试,间隔最长 10 秒。
- 已经连上之后断开,会一直重试,间隔最长 20 秒。
客户端不会放弃重连,除非云网关明确告诉它不要再连了,例如你在控制中心里停止了它,或者云网关拒绝了这条会话。这种情况会在日志里记录原因,命令行客户端的状态面板会显示 permanently disconnected。
数据会话
云网关可以要求客户端在控制会话之外,再额外建立几条数据会话。它们和控制会话一样是独立的加密连接,建立时同样需要用私钥签名。
两者分工不同:控制会话只传控制消息,比如端点的创建和关闭、健康状态、停止和升级指令;用户的流量走数据会话。这样一次大流量的响应不会把控制消息堵在后面,其中一条数据会话断开时,也只会让这一条单独重新拨号。
会话上的端点
会话建立之后,云网关会把端点下发给客户端。端点就是流量到达的入口,同时说明流量要被转发到哪个上游服务。
每个端点包含:端点 ID、类型和协议、上游服务的信息(本机地址,或者要唤起的命令)、健康检查的参数,以及指向它的公网地址。
端点和会话的关系有这几个特点:
- 配置在云端,客户端只负责执行。 你在控制中心创建、修改或者关闭端点,或者用命令行的
proxy add和close,云网关都会通过会话把变更下发给客户端,客户端立即生效。 - 端点的配置不会随客户端消失。 客户端停止或者登出,云端的端点配置和域名都会保留,客户端重新上线后会重新收到它们。
- 转发是隐含的。 流量会交给创建这个端点的客户端,因为它就是流量到达的那条连接。
- 一个客户端可以有任意多个端点。 它们共用同一条会话,所以同时发布多个服务不需要额外的连接。
一次请求怎样到达你的服务
当公网上的一个请求到达 orbitproxy 时,会发生这些事:
- 请求先到达云网关,经过你配置的流量策略,包括身份验证、访问控制、限速和改写。没有通过的请求在这里就被拒绝了,不会到达你的客户端。
- 云网关确定这个请求属于哪个端点、由哪个客户端承载,然后在已经建立的会话上新开一条流,并发送一条消息,告诉客户端端点 ID 和请求的来源地址。
- 客户端收到后,按端点 ID 找到对应的端点,再根据端点的交付方式把这条流交给上游服务。
- 上游的响应沿着同一条流原路返回。
整个过程是在已有的会话上新开一条流,没有任何一步需要连入你的机器,这也是客户端不需要入站端口的原因。
客户端有三种把流交给上游的方式:
| 交付方式 | 适用场景 | 客户端做的事 |
|---|---|---|
| 转发(Forward) | 本机或内网的 HTTP、TCP 服务,以及已经以 HTTP 形态运行的 MCP 服务 | 拨通端点配置的本机地址,在云网关的流和本机连接之间双向复制数据。本机地址拨不通时,这一次请求失败,并在日志里记录 |
| 命令唤起(Exec) | Stdio 形态的 MCP 服务 | 按端点配置的命令启动 MCP 进程,通过标准输入输出与云网关交互。进程按需启动,每个端点最多保持 8 个会话,整个客户端最多 32 个进程,空闲 300 秒后回收 |
| 进程内(In-process) | 使用 SDK 的 Go 应用 | 不连接任何本机地址,而是把连接交给应用通过 net.Listener 接收 |
健康检查
客户端会检查每个端点对应的上游服务是否可用,并把结果上报给云网关,控制中心里端点的状态就来源于此。
健康检查的间隔、超时时间和连续失败次数,都由云网关随端点一起下发。没有指定时,默认每 10 秒检查一次,单次超时 3 秒,失败 1 次就判定为异常。
对于命令唤起的 MCP 服务,客户端还会把进程异常退出的证据,比如退出原因和最后一段错误输出,上报给云网关,方便你在控制中心里直接看到原因。
客户端停止时
端点承载在会话上,所以客户端停止时,它上面的端点就无法转发流量。这是整个模型里最重要的结果,和客户端相关的运维大多是为了应对它:
- 把客户端注册为操作系统服务。 让它开机自启动,并在异常退出后被操作系统拉起。
- 客户端会自己重连。 网络闪断不需要你介入。
客户端停止并不会删除云端的任何配置。客户端重新上线之后,之前的端点和域名继续生效,不需要重新创建。
客户端不做什么
客户端是连接和转发组件,不是一个你需要给它配置规则的代理。认证、访问控制、限速、改写,都由流量策略描述,并在流量到达客户端之前,就已经在云网关里执行完毕。
这也是为什么无论端点是哪种客户端创建的,同一份流量策略的效果完全一致。
后续步骤
- orbitproxy cli:查看
orbitproxy的所有命令和参数。 - 了解 .orbitproxy 目录:了解客户端在本机保存了哪些文件。
- 客户端架构安全性:了解客户端的身份认证和加密连接,以及它为什么不会读取你的数据。