Huly Virtual Network 深入解析:基于 ZeroMQ 的分布式容器网络架构与高可用实践
2026/9/12 1:44:16 网站建设 项目流程

Huly Virtual Network 深入解析:基于 ZeroMQ 的分布式容器网络架构与高可用实践

【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform

导读

Huly Virtual Network(@hcengineering/network-*系列包,仓库位于 foundations/net)是一套面向企业级分布式系统的"虚拟网络"架构:它以 Network / Agent / Container 三层模型为基础,配合 ZeroMQ 高速消息层、引用计数生命周期管理、标签化服务发现、多租户隔离与无状态容器高可用机制,让开发者可以像调用本地对象一样跨机器调度和通信。本文以该仓库 CHANGELOG.md 中 0.7.9 首次公开版本发布的功能清单为主线,结合 docs 系列指南与packages/下四个包的源码实现,系统讲解其核心概念、通信模式、生命周期管理、高可用与多租户方案,并给出可复制运行的部署与编码示例,帮助你掌握这套网络框架的完整实战能力。

一、版本脉络:CHANGELOG 视角下的能力全景

仓库 CHANGELOG.md 记录了 huly.net 的版本演进:

  • Unreleased(待发布):补充了全面的文档与示例、GitHub 社区健康文件(CONTRIBUTING.md、SECURITY.md)以及 Issue / PR 模板——对应 CONTRIBUTING.md 与仓库根部的 SECURITY.md。
  • 0.7.9(2025-10-01,Initial public release):首次公开版本,集中交付了以下能力,它们是本文展开的核心骨架:
类别能力
架构分布式架构、多租户容器管理、支持多客户端的 Server 实现
通信ZeroMQ 基 RPC 通信层、请求/响应模式、事件广播、自动重连与重试
可靠性高可用(无状态容器)、自动故障转移、健康监控、孤儿容器检测与清理
调度跨 Agent 的分布式负载均衡、基于标签的容器发现、容器生命周期引用计数管理
交付客户端库、可配置超时、Docker 部署支持、完整测试套件

下文将逐项深入这些能力对应的文档与源码。

二、核心架构:Network / Agent / Container 三层模型

在动手写代码前,必须先理解 Huly Network 的三个核心概念(详见 CORE_CONCEPTS.md):

  1. Network(网络):中央协调者,维护 Agent 注册表与容器注册表、路由客户端请求、执行引用计数与清理、广播系统事件。
  2. Agent(代理):工作节点,向网络注册并声明自己支持的容器种类(kind),负责容器的创建、健康检查与本地路由;每个 Agent 可托管多个容器。
  3. Container(容器):承载业务逻辑的服务实例,实现统一的Container接口;客户端通过{kind + uuid}或标签定位它。

⚠️ 关键边界(文档多处强调):Network Server 只能以单实例运行,自身不支持 HA/集群,是系统的单点;而Agent 与 Container 支持完整的高可用(无状态容器注册 + 自动故障转移)。生产环境请用 systemd、PM2、Kubernetes 重启策略守护网络服务,Agent 会在网络服务重启后自动重连。

从源码结构看,这一模型被拆为四个包(见 README.md):

  • @hcengineering/network-core:网络核心实现、Agent 管理与容器编排(index.ts 统一导出 API 类型、Agent、容器、网络与代理实现);
  • @hcengineering/network-backrpc:基于 ZeroMQ 的双向 RPC 通信层;
  • @hcengineering/network-client:客户端库,负责连接网络与管理容器;
  • @hcengineering/network-server:多客户端支持的网络服务端。

网络服务端启动示例

import { NetworkImpl, TickManagerImpl } from '@hcengineering/network-core' import { NetworkServer } from '@hcengineering/network-server' const tickManager = new TickManagerImpl(1000) // 心跳 tick 频率 tickManager.start() const network = new NetworkImpl(tickManager) const server = new NetworkServer( network, tickManager, '*', // 绑定所有网卡 3737 // 默认端口 ) console.log('Network server running on port 3737')

三、通信底座:ZeroMQ 双向 RPC 层(network-backrpc)

CHANGELOG 中"ZeroMQ-based RPC communication layer"对应 network-backrpc 包。从其源码 server.ts 可以看到:

  • 服务端基于zeromqRouter 套接字构建(new zmq.Router({ linger: 0, tcpKeepalive: 1, ... })),用于高性能消息路由;
  • 通过RPCClientInfo维护每个客户端的上次活跃时间lastSeen、在途请求集合、请求计数与耗时统计,配合perClientAliveTimeoutSeconds做连接健康管理;
  • 提供requestHandler/helloHandler/closeHandler/onPing等回调接口,形成请求-响应协议骨架,并配套 types.ts 中定义的backrpcOperations与 json-utils.ts 的 JSON 序列化工具。

这意味着客户端与 Agent、Agent 与网络之间的每一次调用,底层都经由 ZeroMQ 消息帧交换,而非传统的 HTTP 长连接,从而获得更低的延迟与更强的并发能力。相关单测见 backrpc.spec.ts 与 zmq.spec.ts。

四、四种通信模式与客户端用法

客户端通过createNetworkClient()连接网络(地址host:port,可传超时秒数),其核心 API(get/list/register/onUpdate/close)定义在 CORE_CONCEPTS.md 中。CHANGELOG 强调的"请求/响应"与"事件广播"对应以下模式:

1. 请求/响应(同步)

const ref = await client.get('user-session' as ContainerKind, {}) const result = await ref.request('processData', { value: 42 }) console.log(result) await ref.close()

2. Fire-and-Forget(异步)

await containerRef.request('logEvent', { event: 'user_login', timestamp: Date.now() })

3. 事件广播(发布/订阅)

容器通过connect(clientId, broadcast)保存客户端的广播函数,需要推送时逐一向所有已连接客户端调用:

const connection = await containerRef.connect() connection.on = async (event) => console.log('Received:', event)

容器侧实现:

connect(clientId: ClientUuid, broadcast: (data: any) => Promise<void>): void { this.clients.set(clientId, broadcast) } // 广播给所有客户端 for (const broadcast of this.clients.values()) { await broadcast({ type: 'update', data: changes }) }

4. 双向流式连接

const connection = await containerRef.connect() connection.on = async (chunk) => console.log('Chunk:', chunk) await connection.request('subscribe', { topic: 'updates' })

资源自动释放(await using)

CHANGELOG 与 AUTO_DISPOSAL_GUIDE.md 提到客户端库对显式资源管理的支持:NetworkClientWithAgents实现了Symbol.dispose/Symbol.asyncDispose短生命周期脚本/测试/纯客户端应用应使用await using自动清理:

async function fetchData() { await using client = createNetworkClient('localhost:3737') await client.waitConnection(5000) const container = await client.get('my-service' as ContainerKind, {}) return await container.request('getData') // 离开作用域时自动 close() }

长驻服务 / 托管 Agent 的服务绝不可用await using,否则函数返回即断开连接;应持有强引用并手动await client.close()

五、容器生命周期:引用计数、超时与孤儿清理

CHANGELOG 中的"Container lifecycle management with reference counting"与"Orphaned container detection and cleanup"是系统自动运维的核心:

  • 每次client.get()对目标容器引用计数 +1,每次containerRef.close()-1;
  • 引用归零后,容器不会立即销毁,而是保留一段可配置的闲置超时时间,超时后自动调用terminate()并移出注册表;
  • 网络持续追踪容器与 Agent 健康状态,失败 Agent 的容器会被移除——这就是"孤儿容器检测与清理"。

时间参数集中在 timeouts.ts:

export const timeouts = { aliveTimeout: 3, // 秒:判定 Agent/Client 失活的超时 unusedContainerTimeout: 5, // 秒:未被引用容器的终止等待时间 pingInterval: 1 // 秒:Agent 心跳间隔 }

与之配套,客户端工厂在创建容器时可用GetOptions指定uuidlabelsextra(工厂附加参数),从而精确控制容器的创建策略。

六、高可用:无状态容器、选主与自动故障转移

CHANGELOG 的"High availability support with stateless containers"与"Automatic failover and health monitoring"由 HA_STATELESS_CONTAINERS.md 与 QUICKSTART_HA.md 完整描述。机制概括为:

  1. 多个 Agent 用同一个 UUID预注册无状态容器,网络对同一 UUID 采用first-wins策略:第一个注册者被接受,其余被拒绝;
  2. 活跃容器终止或所属 Agent 失活时,网络广播移除事件;
  3. 备机收到事件后延迟约 100ms 重新注册(避免惊群效应),先到先得,完成接管——无需外部协调服务即可实现选主。

推荐的生产写法是使用serveAgent()的第三个参数(无状态容器工厂):

await client.serveAgent( 'localhost:3801', {}, // 动态容器工厂 (agentEndpoint) => [{ uuid: sharedUUID, kind: 'my-service' as ContainerKind, endpoint: containerOnAgentEndpointRef(agentEndpoint, sharedUUID), container: new MyService(sharedUUID) }] )

典型应用场景:集群选主、单例服务(如数据库迁移)、主备数据库。需要记住的边界(文档明确列出):无脑裂保护、故障转移期间存在短暂无实例窗口、无状态容器不自动迁移状态。配套测试见 ha-stateless.spec.ts,完整可运行示例见 ha-stateless-container-example.ts。

七、多租户与标签发现

"Multi-tenant container management"与"Label-based container discovery"共同支撑多租户场景(详见 MULTI_TENANT.md):

  • 容器种类(kind):语义化字符串,如user-sessionworkspacequery-enginetransactor,Agent 声明自己支持哪些 kind;
  • 标签(labels):精细选择条件,天然适合表达租户 ID、地域、套餐等级、环境(dev/staging/prod)。
// 按租户标签获取独立工作区(租户即容器) const workspace = await client.get('tenant-workspace' as ContainerKind, { labels: ['tenant:acme-corp'] }) // 或用 extra 传递租户上下文 const workspace2 = await client.get('workspace' as ContainerKind, { extra: { tenantId: 'acme-corp', tier: 'enterprise', region: 'us-west' } })

文档还给出三种隔离深度:容器级隔离(一租户一容器)、共享容器 + 行级安全过滤、数据库级隔离(每租户独立库/模式),以及配额、限流、审计日志与计量计费等 SaaS 化最佳实践。可运行示例见 03-multi-tenant.ts。

八、分布式负载均衡与多 Agent 扩展

"Distributed load balancing across multiple agents"的实现路径是:多个 Agent 注册同一种 kind 的容器工厂,网络在客户端get()时按round-robin在候选 Agent 间分配;新增 Agent 无需中断服务即可动态扩容。客户端可通过list()查看容器注册表、通过onUpdate()订阅 Agent/Container 的 added / updated / removed 事件,实现运维可视化与故障感知(示例见 README.md 中的 Example 7)。

配合"Automatic reconnection and retry logic",当请求失败或容器不可用时,客户端可结合指数退避重试,生产代码模式可参考 05-error-handling-retry.ts:

for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const containerRef = await client.get(kind, options) const result = await containerRef.request('process', { attempt }) return result } catch (err) { await containerRef.close().catch(() => {}) const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000) // 指数退避 await new Promise((resolve) => setTimeout(resolve, delay)) } }

九、可配置超时:适配不同环境

CHANGELOG 的"Configurable timeouts for different environments"在 custom-timeout-example.ts 中给出了环境差异化配置的范式:

// 开发环境:1 小时,便于断点调试 const devClient = createNetworkClient('localhost:3737', 3600) // 生产环境:3 秒默认值,快速释放资源 const prodClient = createNetworkClient('production-network:3737') function createClientForEnvironment(networkHost: string) { const isDevelopment = process.env.NODE_ENV === 'development' return createNetworkClient(networkHost, isDevelopment ? 3600 : 3) }

超时语义分为两类:客户端连接存活超时(影响 Agent 失活判定)与容器闲置终止超时(影响未引用容器的保留时长),前者通过createNetworkClient第二参数设置,后者与aliveTimeout/unusedContainerTimeout全局默认值相关(见 timeouts.ts)。

十、测试套件与 Docker 部署

测试

CHANGELOG 声明了"Comprehensive test suite"。仓库中的测试覆盖三个层次:

  • 核心层:packages/core/src/test含网络行为、HA 无状态、Agent 扩展、alive checkin、代理与工具函数测试;
  • RPC 层:backrpc.spec.ts、zmq.spec.ts;
  • 客户端层:packages/client/src/tests覆盖连接建立、容器连接、释放与扩展行为。

另外 tests 目录提供 docker-compose 与 prepare 脚本支撑端到端集成测试,test-examples.sh 用于批量验证示例脚本。在packages/core下运行rushx test即可执行单元测试。

Docker 部署

"Docker deployment support"由 network-pod(含 Dockerfile)与 network-tool 提供。完整的生产部署(Docker Compose / Kubernetes、环境变量与配置文件、Prometheus 指标、结构化日志、健康检查、备份恢复与滚动更新)详见 PRODUCTION_DEPLOYMENT.md。快速上手(本地开发安装、三终端跑通 Hello World)见 QUICKSTART.md。

十一、能力边界与运维提醒

综合 CHANGELOG 与各文档,以下边界必须写进你的架构评估:

  1. Network Server 单实例:不支持集群与双活,是系统单点;建议以进程守护 + 快速重启 + 健康监控缓解,Agent 会自动重连(README.md)。
  2. 故障转移有短暂窗口:无状态容器接管存在约 100ms 延迟,系统是最终一致的。
  3. 无脑裂保护、无状态迁移:跨分区部署时需自行设计冗余与状态同步策略(HA_STATELESS_CONTAINERS.md)。
  4. 多租户隔离靠约定:网络层提供 kind / labels / 引用管理,数据级隔离(行级、库级、内存级)需在容器内实现(MULTI_TENANT.md)。

结语

从 CHANGELOG.md 的功能清单出发,本文沿"分布式架构 → ZeroMQ 通信 → 通信模式 → 生命周期 → 高可用 → 多租户 → 负载均衡 → 超时 → 测试与部署"的脉络,把 Huly Virtual Network 的核心设计逐一落地到文档与源码证据上。若要进一步动手,建议按以下顺序深入仓库:先跑通 examples/01-basic-container-request-response.ts,再依次实验 02-event-broadcasting.ts(事件广播)、03-multi-tenant.ts(多租户)、04-complete-production-setup.ts(生产级组合)与 ha-stateless-container-example.ts(高可用),最后参照 PRODUCTION_DEPLOYMENT.md 完成容器化上线。

【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询