Apache Texera 1.2.0-incubating 架构与核心概念详解

基于 v1.2.0-incubating 源码树与一次真实编译启动的实测,讲清 Apache Texera 的总体分层、sbt 模块划分、Web 服务角色、amber 执行引擎目录结构与数据存储链路

Apache TexeraApache Texera2026/10/15

Apache Texera 1.2.0-incubating 架构与核心概念详解

目标:以 v1.2.0-incubating 源码树(commit c3aa6e4ba36bdd0cdc9f76bd7896c024dda392b3)为底本,配合一次真实的后端编译与启动实测,讲清 Texera 的总体分层、sbt 模块划分、各 Web 服务角色、amber 执行引擎目录结构与数据存储链路。已在 Ubuntu 24.04(x86_64)+ OpenJDK 17.0.20.1 + sbt 1.12.9 + PostgreSQL 16 环境实测通过。

一、环境信息

本篇所有结论均来自对本地源码树的直接检视与真实启动实测,先固定基线:

  • 源码版本:v1.2.0-incubating(git describe 输出,commit c3aa6e4ba36bdd0cdc9f76bd7896c024dda392b3,2026-07-30)
  • 构建工具:sbt 1.12.9(Scala 2.13.18 编译产物)
  • JDK:OpenJDK 17.0.20.1
  • 数据库:PostgreSQL 16.15(sql/texera_ddl.sql 初始化,28 条 CREATE TABLE)
  • 前端:Angular 21(frontend/package.json version=1.2.0-incubating,engines node>=24,packageManager yarn@4.14.1)
  • 实测运行产物:amber/target/universal/stage/bin/ 下的 4 个启动脚本
  • 检视命令示例(实时回显):
cd texera-src && git describe --tags && git log -1 --format="%H %cd" --date=short
v1.2.0-incubating
c3aa6e4ba36bdd0cdc9f76bd7896c024dda392b3 2026-07-30

二、项目定位与总体分层

Texera 是一个可协作的数据分析平台:用户在浏览器里拖拽算子组装工作流,平台把工作流编译成物理计划交给执行引擎分布式运行,结果再以表格或图表回显到前端。整个仓库按职责分成三层:

层组成说明
前端层frontend/(Angular 21 + TypeScript)工作流编辑器、算子面板、结果可视化、协同编辑 UI
服务层12 个子模块中的 7 个 Web 服务登录鉴权、工作流 CRUD、数据集、编译校验、计算单元管理等 REST/WebSocket 服务
执行层amber/(WorkflowExecutionService 模块,amber 引擎)把逻辑计划调度到 worker 执行,含容错与日志回放

三层之间以 HTTP(/api/*)、WebSocket(/wsapi/*)与数据库(PostgreSQL/Iceberg/S3 协议对象存储)连接。官方开发者文档(docs/contribution-guidelines/guide-for-developers.md)明确给出了各服务的分工表,本篇第四章逐项对照实测。

💡 技术拓展:同类数据科学平台中,JupyterHub 偏重单用户交互式 Notebook 会话分发,Apache Zeppelin 偏重解释器制的 Notebook 分析,而 Texera 的差异点在于「工作流 + 多算子图 + 协同编辑 + 分布式执行引擎」的组合:它把分析过程显式建模为有向图并交由 amber 引擎调度执行,本系列文章即以 Texera 1.2.0-incubating 为准。

三、代码仓库与 sbt 模块划分

仓库根 build.sbt 用 lazy val 声明了各模块。实测 grep -nE "lazy val [A-Za-z]+ \(project" build.sbt 的结果(节选):

112:lazy val DAO = (project in file("common/dao")).settings(asfLicensingSettings)
113:lazy val Config = (project in file("common/config")).settings(asfLicensingSettings)
114:lazy val Auth = (project in file("common/auth"))
117:lazy val ConfigService = (project in file("config-service"))
126:lazy val AccessControlService = (project in file("access-control-service"))
140:lazy val PyBuilder = (project in file("common/pybuilder"))
145:lazy val WorkflowCore = (project in file("common/workflow-core"))
150:lazy val ComputingUnitManagingService = (project in file("computing-unit-managing-service"))
165:lazy val FileService = (project in file("file-service"))
179:lazy val WorkflowOperator = (project in file("common/workflow-operator")).settings(asfLicensingSettingsWithVendored).dependsOn(WorkflowCore)
180:lazy val WorkflowCompilingService = (project in file("workflow-compiling-service"))
192:lazy val WorkflowExecutionService = (project in file("amber"))
213:lazy val TexeraProject = (project in file("."))

按依赖关系可以归为四类:

类别模块职责
基础库DAO、Config、Auth、PyBuilder数据库访问(jOOQ 生成代码)、配置加载、JWT 鉴权、Python 执行器构建
领域库WorkflowCore、WorkflowOperator工作流逻辑计划核心模型、全部算子描述符(LogicalOp 及其子类)
Web 服务ConfigService、TexeraWebApplication(amber 内)、FileService、WorkflowCompilingService、ComputingUnitManagingService、AccessControlService对前端暴露 REST/WebSocket 接口
可执行体WorkflowExecutionService(amber)既包含 TexeraWebApplication 主服务,也包含 ComputingUnitMaster/Worker 执行角色

一次真实的后端全量编译(sbt compile,首编译 82 秒,不含依赖下载)实测回显节选:

[info] compiling 258 Scala sources and 50 Java sources to /work/texera-src/common/workflow-operator/target/scala-2.13/classes ...
[info] compiling 9 Scala sources to /work/texera-src/computing-unit-managing-service/target/scala-2.13/classes ...
[info] done compiling
[warn] two warnings found
[success] Total time: 82 s (0:01:22.0)

⚠️ 注意:sbt 编译的模块日志按依赖序展开,common/workflow-operator 是体量最大的模块(258 个 Scala 源文件),首次冷编译的时间主要花在这里与 amber 模块。

四、Web 服务角色与端口

官方开发者指南给出了每个服务的角色定位,实测对照如下(翻译整理自 docs/contribution-guidelines/guide-for-developers.md 第 197-204 行的服务表):

服务源码位置角色实测状态
ConfigServiceconfig-service/向前端提供系统配置数据编译通过,本地单机模式非必需
TexeraWebApplicationamber/.../web/TexeraWebApplication.scala用户登录、社区资源读写、算子元数据加载实测启动成功,8080/8081 监听
FileServicefile-service/数据集管理、访问控制与读写编译通过
WorkflowCompilingServiceworkflow-compiling-service/工作流构建期传播 schema 并做静态检查编译通过
ComputingUnitMasteramber/.../web/ComputingUnitMaster.scala工作流执行主节点官方要求先于 Worker 启动
ComputingUnitWorkeramber/.../web/ComputingUnitWorker.scala计算集群中的 worker 节点(非 Web 服务)stage 产物含启动脚本
ComputingUnitManagingServicecomputing-unit-managing-service/管理各类型计算单元的生命周期与连接编译通过
AccessControlServiceaccess-control-service/计算单元请求鉴权,仅 Kubernetes 部署需要本地开发可不启动

TexeraWebApplication 是 Dropwizard 应用:Jetty 承载 8080(应用)与 8081(管理)两个端口,Jersey 挂载 /api/* 前缀,WebSocket 端点 /wsapi/collab 由 CollaborationResource 以 @ServerEndpoint 注解提供(协同编辑通道)。端口定义在 amber/src/main/resources/web-config.yml:

server:
  applicationContextPath: /
  applicationConnectors:
    - type: http
      port: 8080
  adminConnectors:
    - type: http
      port: 8081

TexeraWebApplication.scala 第 129-163 行依次 register 了 24 个 Jersey 资源,实测摘录如下(按源码顺序):

environment.jersey.register(classOf[SessionHandler])
environment.jersey.register(classOf[SystemMetadataResource])
environment.jersey.register(classOf[HealthCheckResource])
environment.jersey.register(classOf[AuthResource])
environment.jersey.register(classOf[GoogleAuthResource])
environment.jersey.register(classOf[UserConfigResource])
environment.jersey.register(classOf[AdminUserResource])
environment.jersey.register(classOf[PublicProjectResource])
environment.jersey.register(classOf[WorkflowAccessResource])
environment.jersey.register(classOf[WorkflowResource])
environment.jersey.register(classOf[HubResource])
environment.jersey.register(classOf[UserResource])
environment.jersey.register(classOf[WorkflowVersionResource])
environment.jersey.register(classOf[ProjectResource])
environment.jersey.register(classOf[ProjectAccessResource])
environment.jersey.register(classOf[WorkflowExecutionsResource])
environment.jersey.register(classOf[DashboardResource])
environment.jersey.register(classOf[GmailResource])
environment.jersey.register(classOf[AdminExecutionResource])
environment.jersey.register(classOf[UserQuotaResource])
environment.jersey.register(classOf[AdminSettingsResource])
environment.jersey.register(classOf[AIAssistantResource])
environment.jersey.register(classOf[HuggingFaceModelResource])

启动后 8081 管理端口内置 Dropwizard 健康检查,实测回显:

curl -s http://localhost:8081/healthcheck
{"deadlocks":{"healthy":true}}

五、amber 执行引擎结构

amber(WorkflowExecutionService 模块)的引擎代码位于 amber/src/main/scala/org/apache/texera/amber/engine/,实测目录树如下:

engine/
├── architecture/
│   ├── common/
│   ├── controller/
│   ├── deploysemantics/
│   ├── logreplay/
│   ├── messaginglayer/
│   ├── pythonworker/
│   ├── scheduling/
│   ├── sendsemantics/
│   └── worker/
└── common/
    ├── ambermessage/
    ├── client/
    ├── rpc/
    ├── statetransition/
    ├── storage/
    └── virtualidentity/

各子目录职责:

  • messaginglayer:actor 消息层,封装节点间通信与序号去重。
  • controller:执行控制器,驱动工作流状态机、区域终止与恢复决策。
  • worker:单个算子实例(WorkerActor)的执行与状态迁移。
  • deploysemantics:算子实例的部署语义(单实例、按分区并行等)。
  • sendsemantics:数据分发的传输语义(one-to-one、all-to-all 等批量发送策略)。
  • logreplay:故障恢复所依赖的日志回放机制。
  • scheduling:工作流级别的调度策略。
  • pythonworker:与 Python 执行器(PyBuilder 构建)之间的跨语言桥接。
  • common/virtualidentity:全链路虚拟身份(execution/operator/worker 各级 ID)。

sbt "WorkflowExecutionService/stage" 打包后产生 4 个可执行入口(实测 ls amber/target/universal/stage/bin/ 回显):

amber
amber.bat
computing-unit-master
computing-unit-master.bat
computing-unit-worker
computing-unit-worker.bat
texera-web-application
texera-web-application.bat

对应关系:texera-web-application 启动第四章的 Web 服务;computing-unit-master/computing-unit-worker 启动执行主节点与 worker;amber 入口保留给单进程模式。

六、数据与存储链路

Texera 的持久化分两条线:关系型元数据与工作流结果/数据集对象。

6.1 关系型元数据(PostgreSQL + jOOQ)

common/config/src/main/resources/storage.conf 第 138 行定义了主库连接(原文节选):

url = "jdbc:postgresql://localhost:5432/texera_db?currentSchema=texera_db,public"

数据库与 schema 由 sql/texera_ddl.sql 一次性创建(先 DROP/CREATE DATABASE texera_db,再 CREATE SCHEMA texera_db,随后 28 条 CREATE TABLE 建齐用户、工作流、项目、执行等表,并在第 439 行起创建 pgroonga 扩展与全文索引辅助函数)。sbt 模块 DAO 在编译前运行 DAO/jooqGenerate,从该库反向生成 jOOQ 代码到 common/dao/target/src_managed,运行期由 Hikari 连接池管理连接(启动日志实测出现 texera-hikari - Start completed.)。

6.2 工作流结果(Apache Iceberg)

storage.conf 的 storage.iceberg 段配置结果表存储,catalog.type 支持 hadoop、rest、postgres 三种,默认 postgres,指向 localhost:5432/texera_iceberg_catalog(由 sql/iceberg_postgres_catalog.sql 初始化)。结果按命名空间分表:operator-port-result(端口数据)、operator-console-messages(控制台消息)、workflow-runtime-statistics(运行统计)、operator-port-state(状态)。

6.3 数据集与对象存储(LakeFS + S3 协议)

storage.conf 的 storage.lakefs 段定义数据集版本化存储(默认 http://localhost:8000/api/v1,示例密钥 AKIAIOSFOLKFSSAMPLES),块存储类型 s3、桶名 texera-dataset;storage.s3 段定义对象存储端点(默认 http://localhost:9000)、大对象桶 texera-large-binaries 与 16MB 分片上传尺寸。

6.4 配置覆盖约定

storage.conf 中每一项都重复声明了一次 =${?STORAGE_...} 形式的 HOCON 环境变量回退,例如 type = ${?STORAGE_ICEBERG_CATALOG_TYPE}。这意味着所有存储配置都可以不改动文件、仅通过 STORAGE_ 前缀环境变量覆盖,这是多环境部署与编排化部署的统一入口。其余配置文件:web-config.yml(端口与日志)、gui.conf(前端参数)、user-system.conf(用户系统)、udf.conf(Python 解释器路径)。

七、前端与工作流模型

前端为 Angular 21 单页应用,构建产物 frontend/dist(实测 39 MB,入口 index.html 18420 字节,页面内嵌版本戳 build-version: 1.2.0-incubating.261015373)。服务层通过 FileAssetsBundle 把该目录作为静态资源挂载到根路径,启动日志实测:

Registering FileAssetBundle with servlet name file-assets for request path /* from file system /work/texera-src/amber/../../frontend/dist

注意该路径是相对启动目录的 ../../frontend/dist 推导,因此独立运行 stage 产物时若目录相对关系不成立,静态页面会 404(详见第九章)。

工作流的持久化形态是一份 JSON。仓库自带的示例 bin/single-node/examples/workflows/[Example] Data Exploration on Movies Dataset.json 实测解析出的顶层结构:

top keys: ['operators', 'operatorPositions', 'links', 'commentBoxes', 'settings']

单个算子对象与一条连线(link)的字段(同一文件实测):

operator keys: ['operatorID', 'operatorType', 'operatorVersion', 'operatorProperties',
                'inputPorts', 'outputPorts', 'showAdvanced', 'isDisabled',
                'customDisplayName', 'dynamicInputPorts', 'dynamicOutputPorts', 'viewResult']
operator sample: {"operatorID": "CSVFileScan-operator-ddb8baf2-...", "operatorType": "CSVFileScan",
                  "customDisplayName": "Read Movie Dataset"}
link sample: {"linkID": "3fba9036-...", "source": {"operatorID": "Aggregate-operator-...", "portID": "output-0"},
              "target": {"operatorID": "PieChart-operator-...", "portID": "input-0"}}

字段要点:operatorType 决定反序列化到哪个算子描述符类(类型注册机制见本系列算子篇);operatorProperties 是该算子的参数键值对,与算子元数据里的 JSON Schema 对应;operatorPositions/commentBoxes/settings 只服务画布呈现,执行引擎不消费。

八、一次完整启动的实测时序

以下是 stage 产物在已就绪的 PostgreSQL 之上冷启动的完整时序(日志时间戳均为实测值):

[12:43:12,848] Registering FileAssetBundle with servlet name file-assets for request path /* from file system /work/texera-src/amber/../../frontend/dist
[12:43:13,355] [com.zaxxer.hikari.HikariDataSource] texera-hikari - Start completed.
[12:43:14,142] [io.dropwizard.server.ServerFactory] - Starting TexeraWebApplication
[12:44:00,990] Started i.d.j.MutableServletContextHandler@16f62062{/,null,AVAILABLE}
[12:44:01,010] Started application@7846913f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[12:44:01,014] Started admin@48da64f2{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
[12:44:01,014] [org.eclipse.jetty.server.Server] - Started @4302ms

启动后约 4302 毫秒 Jetty 完成绑定,进程 RSS 实测约 410 MB(-J-Xmx512m 参数下)。随后逐项验证核心 API(实测回显):

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/api/resources/operator-metadata
200
curl -s -X POST -H "Content-Type: application/json" \
  -d '{"username":"doc_writer","password":"q1w2e3r4"}' \
  http://localhost:8080/api/auth/register
{"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkb2Nfd3JpdGVyIiwidXNlcklkIjozLCJnb29nbGVJZCI6bnVsbCwiZW1haWwiOiJkb2Nfd3JpdGVyIiwicm9sZSI6IlJFU1RSSUNURUQiLCJnb29nbGVBdmF0YXIiOm51bGwsImV4cCI6MTc5MjY3MjkyMH0.ay-4_EStOtpyy91X7563ndxg6nM8z3fOoUVz7K-cjwU"}

首次注册即返回 JWT accessToken(新用户角色为 RESTRICTED,JWT 载荷内 role 字段可解码确认);同一用户名重复注册返回 406 与 {"code":406,"message":"Username exists already."};登录接口 POST /api/auth/login 同样返回 200 与新签发的 JWT。

九、注意事项与常见问题

9.1 stage 模式下静态页面 404 是已知边界

FileAssetsBundle 注册的静态目录是相对启动目录上两级推导的(../../frontend/dist)。以 stage 产物独立启动时该相对路径不指向真实 dist,实测 GET / 返回 404,同时 /api/* 一切正常;将 stage 目录软链到 frontend/dist 后重启仍为 404。结论:静态 GUI 服务面向开发模式(在仓库内目录启动,或 IDE 直接运行主类);独立部署应确保目录相对关系与仓库布局一致,或以反向代理托管前端静态文件。

9.2 启动日志中的 jgit 异常可以忽略

启动早期会出现一段 org.eclipse.jgit.errors.RepositoryNotFoundException: repository not found: /work/texera-src/amber 的堆栈,来自 OPVersion 尝试从当前工作目录向上定位 git 仓库以读取算子版本号。该异常被捕获后进程继续启动,API 全部可用,不影响功能;如希望消除,可在仓库根目录启动。

9.3 未配置 user-sys.domain 会出现横幅告警

启动日志实测出现:

[WARN] The user-sys.domain is not configured, and the "Sent from:" field in the email will not include a domain!
Please configure user-sys.domain=your.domain.com or set the environment variable/system property USER_SYS_DOMAIN

仅影响邮件外发域名的显示,本地验证可忽略;生产部署建议配置该环境变量。

9.4 缺少 jOOQ 生成代码时编译报 27 个错误

跳过 DAO/jooqGenerate 直接 sbt compile 会集中报 object jooq is not a member of package org.apache.texera.dao(实测 27 errors)。另外注意:数据库不可达时 DAO/jooqGenerate 任务本身以 [warn] JOOQ code generation failed: Connection to localhost:5432 refused 告终但 sbt 退出码为 0,不能以退出码判断该步成败,需回看日志。

9.5 首次编译会出现 protoc 告警

实测日志:[warn] protoc or protoc-gen-python_betterproto not found on PATH; skipping Python proto generation.。这只影响 Python 执行器的 proto 重生成,Java/Scala 编译与 Web 服务启动不受影响。

十、参考链接

  • Apache Texera 官网:https://texera.apache.org/
  • 源码仓库:https://github.com/apache/texera(tag v1.2.0-incubating)
  • 开发者指南(服务角色表与本地启动说明):仓库内 docs/contribution-guidelines/guide-for-developers.md
  • 存储配置说明:仓库内 common/config/src/main/resources/storage.conf
  • Web 端口与日志配置:仓库内 amber/src/main/resources/web-config.yml
  • 数据库 DDL:仓库内 sql/texera_ddl.sql、sql/iceberg_postgres_catalog.sql
  • Apache 软件基金会孵化器声明:https://incubator.apache.org/