Anarlog Enterprise Control Plane 部署实战:企业级会议捕获 API 的自托管与配置指南
2026/9/16 13:29:16 网站建设 项目流程

Anarlog Enterprise Control Plane 部署实战:企业级会议捕获 API 的自托管与配置指南

【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarlog

导读

Anarlog Enterprise control plane 是 anarlog 开源仓库中以商业许可提供的企业级服务,它将 workspace 维度的会议捕获 API 与自动 PostgreSQL 迁移、fail-closed 启动配置、优雅停机打包在一起:捕获事件被持久化追加到数据库,每个 revision 被投影为共享的 session-ingest 契约,再投递给已授权的客户端。本文以 enterprise/control-plane/README.md 为主体,结合仓库内的 Compose 编排、Dockerfile 与 Rust 源码实现,完整讲解评估部署、Infisical 密钥注入、全部环境变量、健康检查、REST API 路由与捕获作业租约协议,并给出可在仓库内直接验证的命令与配置。

服务定位:企业捕获 API 的控制面

control plane 是一个独立的二进制服务,入口位于 enterprise/control-plane/src/main.rs,其职责可以概括为四件事:

  1. 持久化捕获事件:以 provider-neutral(供应商无关)的形式追加 capture events,每个被接受的事件会原子性地推进 PostgreSQL checkpoint;
  2. 投影会话契约:每个 revision 通过 enterprise/control-plane/src/projector.rs 投影为anlg-session-ingest定义的共享会话契约(SessionIngestEnvelope);
  3. 投递给授权客户端:客户端按 consumer 分页拉取投递项并显式 ack;
  4. 自动运维:启动时自动应用 SQL 迁移、连接池管理、优雅停机。

从依赖来看,它复用anlg-meeting-capture(捕获线缆契约)与anlg-session-ingest(会话摄入契约)两个共享 crate,并以anarlog-enterprise-zoom-rtms-worker作为 Zoom RTMS 捕获 worker,见 enterprise/control-plane/Cargo.toml。控制面通过 trait 抽象存储与鉴权(ControlPlaneStoreWorkspaceAuthenticator),核心逻辑位于 enterprise/control-plane/src/api.rs、store.rs、auth.rs、capture.rs、schedule.rs、zoom.rs。

评估部署:Docker Compose v2 一键启动

前置条件与 .env 准备

评估部署需要 Docker 与 Compose v2。从仓库根目录执行:

cp enterprise/control-plane/.env.sample enterprise/control-plane/.env

enterprise/control-plane/.env.sample 提供以下模板变量:

POSTGRES_DB=anarlog POSTGRES_USER=anarlog POSTGRES_PASSWORD=replace-with-random-hex ANARLOG_ENTERPRISE_DATABASE_URL=postgres://anarlog:replace-with-random-hex@postgres:5432/anarlog ANARLOG_ENTERPRISE_DATABASE_MAX_CONNECTIONS=10 ANARLOG_ENTERPRISE_WORKSPACE_TOKENS={"evaluation-workspace":"replace-with-at-least-32-random-characters"} ANARLOG_ENTERPRISE_PORT=8080 RUST_LOG=info,tower_http=info

按 README 要求,替换两处数据库密码为相同的随机十六进制值(十六进制值可避免POSTGRES_PASSWORDANARLOG_ENTERPRISE_DATABASE_URL中 URL 编码差异导致的不一致),并将 workspace bearer token 替换为至少 32 个随机字符

启动、验证与停止

docker compose \ --file enterprise/control-plane/compose.yaml \ --env-file enterprise/control-plane/.env \ up --build --wait --detach

enterprise/control-plane/compose.yaml 中值得注意的编排细节:

  • postgres使用固定 digest 的postgres:17-alpine,自带pg_isready健康检查(5s 间隔、12 次重试);
  • control-planeread_only: true挂载只读根文件系统,/tmp使用 tmpfs(noexec,nosuid,size=16m),两者都带no-new-privileges: true
  • 端口默认只绑定127.0.0.1:${ANARLOG_ENTERPRISE_PORT:-8080}:8080不对外发布 PostgreSQL
  • 数据持久化仅通过postgres-datavolume,docker compose down不会删除数据库数据。

启动后验证 API 与数据库就绪:

curl --fail http://127.0.0.1:8080/health/ready curl --fail \ --header 'Authorization: Bearer YOUR_WORKSPACE_TOKEN' \ 'http://127.0.0.1:8080/v1/workspaces/evaluation-workspace/session-envelopes?consumerId=evaluation-device&after=0'

停止服务(保留数据):

docker compose \ --file enterprise/control-plane/compose.yaml \ --env-file enterprise/control-plane/.env \ down

镜像与运行约束

enterprise/control-plane/Dockerfile 揭示了镜像的加固策略:

  • 构建与运行镜像均使用固定的 Debian/Rust 基础镜像 digestrust:1.94.0-bookwormdebian:bookworm-slim);
  • 以 UID/GID10001的非 root 用户anarlog运行,USER 10001:10001
  • 内置HEALTHCHECK(10s 间隔,curl/health/ready);
  • 默认ENV ANARLOG_ENTERPRISE_BIND_ADDRESS=0.0.0.0:8080RUST_LOG=info,tower_http=info

README 强调:在将 API 暴露到 localhost 之外前,应在可信反向代理处终止 TLS

配置总览:环境变量与 fail-closed 启动

完整变量表

变量必填用途
ANARLOG_ENTERPRISE_DATABASE_URLPostgreSQL 连接 URL。数据库不可用或迁移失败时启动失败。
ANARLOG_ENTERPRISE_WORKSPACE_TOKENSJSON 对象,将 workspace ID 映射到 bearer token。至少需要 1 个 32–512 字节的唯一 token。
ANARLOG_ENTERPRISE_BIND_ADDRESS监听地址。默认0.0.0.0:8080;镜像中设置相同值。
ANARLOG_ENTERPRISE_DATABASE_MAX_CONNECTIONSPostgreSQL 连接池大小,1–100。默认10
ANARLOG_ENTERPRISE_ZOOM_CLIENT_ID成组Zoom RTMS 应用 client ID。
ANARLOG_ENTERPRISE_ZOOM_CLIENT_SECRET成组Zoom RTMS 应用 client secret。
ANARLOG_ENTERPRISE_ZOOM_WEBHOOK_SECRET成组Zoom webhook 密钥,用于校验签名请求体。
ANARLOG_ENTERPRISE_ZOOM_ACCOUNT_WORKSPACES成组JSON 对象,将已签名的 Zoom account ID 映射到已配置的 workspace ID。
RUST_LOG标准 tracing 过滤规则。默认输出请求与服务信息,不导出遥测。

源码级的校验逻辑

这些约束并不是文档空谈,而是由 enterprise/control-plane/src/config.rs 的Config::from_values_with_zoom在进程启动时强制执行的:

  • 数据库 URL 必须以postgres://postgresql://开头,否则报InvalidDatabaseUrl
  • bind_address必须可解析为SocketAddr,默认0.0.0.0:8080
  • DATABASE_MAX_CONNECTIONS解析为u32后必须在1..=100区间,默认10,数据库获取连接超时固定 10 秒;
  • workspace token 用serde_json解析为 JSON 对象(WorkspaceTokens),空对象报EmptyWorkspaceTokens;workspace ID 长度 1–128 且只允许 ASCII 字母数字与-_.;token 长度必须在 32–512 字节之间,否则报InvalidWorkspaceToken
  • 四个 Zoom 变量必须整体出现:全缺席 →zoom=None,部分出现 →IncompleteZoomConfigurationANARLOG_ENTERPRISE_ZOOM_ACCOUNT_WORKSPACES只能引用ANARLOG_ENTERPRISE_WORKSPACE_TOKENS中已存在的 workspace,否则报UnknownZoomWorkspace
  • 此外还支持可选的离线 license 变量(LICENSELICENSE_KEY必须成对出现),逻辑见 enterprise/control-plane/src/license.rs。

对应测试位于 enterprise/control-plane/src/config.rs 的#[cfg(test)]模块,覆盖了最小配置、空凭据失败、短 token 拒绝(且错误消息不回显 token 本身)、Zoom 成组校验等场景——这也是"fail-closed"(启动即失败,绝不带病运行)的实践证据。

健康检查语义

  • GET /health/live:进程级存活探针,恒返回{"status":"ok"},不触碰数据库;
  • GET /health/ready:就绪探针,执行store.readiness()检查 PostgreSQL,失败时返回 503{"status":"not_ready"}

实现见 enterprise/control-plane/src/api.rs,镜像的HEALTHCHECK正是基于/health/ready

使用 Infisical 注入密钥

该部署接受的所有密钥都来自环境变量,因此 Infisical 可以在不生成.env文件的情况下注入。将.env.sample中的变量存入一个 Infisical 环境,然后运行:

infisical run --env=prod -- \ docker compose \ --file enterprise/control-plane/compose.yaml \ up --build --wait --detach

注意事项(README 明确要求):

  • 机器身份(machine identity)与项目选项请参考infisical run官方命令文档;
  • 生产环境 Compose 进程不要使用--watch;当凭据轮换时应执行受控重启;
  • Infisical 应在进程启动时注入这些值;服务本身不会主动获取、持久化或记录供应商凭据(Zoom client secret、webhook secret 等在Debug输出中也会被遮蔽,见 config.rs 的测试断言)。

捕获作业与租约协议:事件追加的可靠性机制

READ ME 中关于 capture job 的描述是理解系统可靠性的关键:

  • 捕获 worker 通过POST /v1/workspaces/{workspace_id}/capture-jobs/{job_id}创建持久化作业;
  • 通过/claim认领作业,并持续通过/lease续租返回的60 秒 fencing lease
  • 每次追加到/events的新事件必须携带该租约身份(worker_id、lease_id、epoch);
  • 租约过期后可用更高 epoch 重新认领,从而阻止前一个 worker 继续推进作业;已持久化的完全相同事件重放仍然安全;
  • 事件 ID 与零基序号(zero-based sequence)是幂等键:每个被接受的事件原子性推进 PostgreSQL checkpoint 并发布一个 delivery revision;冲突的 ID、序号、生命周期转换或过期租约都会 fail closed。

这些常量在代码中有据可查:租约时长CAPTURE_LEASE_DURATION = 60s(api.rs),claim 时要求epoch > 0(api.rs),事件请求体契约AppendCaptureEventRequestCaptureJobLease等类型由anlg-meeting-capture::wire统一导出(capture.rs),其数据表由 enterprise/control-plane/migrations/0003_capture_job_leases.sql 承载。

REST API 路由一览

由 api.rs 的router()注册的路由如下:

方法与路径说明
GET /health/live进程存活探针
GET /health/readyPostgreSQL 就绪探针
POST|GET /v1/workspaces/{workspace_id}/capture-jobs/{job_id}创建捕获作业 / 读取捕获 checkpoint
POST /v1/workspaces/{workspace_id}/capture-jobs/{job_id}/events追加捕获事件(携带租约身份)
POST /v1/workspaces/{workspace_id}/capture-jobs/{job_id}/claim认领作业,返回 60s 租约
POST /v1/workspaces/{workspace_id}/capture-jobs/{job_id}/lease续租
GET /v1/workspaces/{workspace_id}/session-envelopes分页拉取会话投递(consumerId必填,after/limit可选,limit 默认 10、上限 100)
POST /v1/workspaces/{workspace_id}/session-envelopes/{job_id}/ack按 revision + contentHash 显式确认投递
GET /v1/workspaces/{workspace_id}/sessions/{job_id}读取会话
GET|PUT /v1/workspaces/{workspace_id}/capture-policy读写捕获策略
PUT /v1/workspaces/{workspace_id}/calendar-events批量 upsert 日历事件(单批上限 500),生成定时捕获
GET|POST /v1/workspaces/{workspace_id}/scheduled-captures列出 / 立即触发到期的定时捕获
DELETE /v1/workspaces/{workspace_id}/scheduled-captures/{calendar_event_id}取消定时捕获
POST /webhooks/zoom(仅在配置 Zoom 后挂载)Zoom webhook 入口,校验x-zm-request-timestampx-zm-signature

鉴权与错误语义

所有捕获与投递路由都要求Authorization: Bearer <token>;token 被 SHA-256 哈希后与 workspace 映射比对(StaticTokenAuthenticator,见 auth.rs),并且拒绝用某 workspace 的 token 访问其他 workspace(返回 403workspace_forbidden)。若配置了离线 license,还会校验 license 是否授权该 workspace(api.rs)。

错误响应统一为{"error":{"code","message"}}结构:冲突类错误使用 409(如revision_conflictcapture_event_conflictcapture_lease_lost),非法事件返回 422invalid_capture_event,未授权返回 401 并附带WWW-Authenticate: Bearer

定时捕获调度

控制面在启动时还会tokio::spawn一个每 30 秒触发的调度循环(lib.rs),调用dispatch_due_scheduled_captures(Utc::now())将到期的日历捕获作业批量投递;对应 SQL 迁移为 0005_scheduled_captures.sql。定时作业 ID 以cal-前缀标识(api.rs)。

优雅停机与启动流程

run()(lib.rs)先构建状态(连接池、自动迁移、可选的 Zoom 恢复与 license),再绑定监听地址,并通过axum::serve(...).with_graceful_shutdown(...)等待 SIGINT(Ctrl-C)或 SIGTERM,收到信号后记录日志并优雅退出(lib.rs)。Zoom 配置存在时,启动阶段还会执行dispatcher.recover_pending()恢复未完成的持久化投递并spawn_recovery()(lib.rs)。

测试与验收路径

仓库为控制面提供了可复现的验证手段:

  • 单元测试:Configauth的鉴权与重复 token 拒绝、API 错误映射等(config.rs、auth.rs);
  • 集成测试:enterprise/control-plane/tests/postgres.rs、api.rs、convergence.rs、upgrade.rs;
  • 冒烟脚本:enterprise/control-plane/tests/compose-smoke.sh 可直接用于验证上述docker compose up后的健康检查与投递拉取链路。

已知边界

README 明确说明:静态 token 映射面向评估部署,位于WorkspaceAuthenticator接口之后;生产级 OIDC、SCIM、离线 license 强制、对象存储与会议浏览器 worker 均不在本服务范围内,属后续演进方向。部署时应将镜像与 Compose 中固定 digest 的依赖一并纳入供应链审查,并在反向代理层完成 TLS 终结。

【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarlog

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

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

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

立即咨询