Azkaban-3.51.0裸机安装实战:从零部署Web+Executor+MySQL三体架构

📅 发布时间:2026/7/11 7:50:56
Azkaban-3.51.0裸机安装实战:从零部署Web+Executor+MySQL三体架构 1. 为什么今天还要亲手装 Azkaban不是早该被 Airflow/Kubeflow 取代了吗我去年在一家中型数据平台团队做架构支持接手的第一个需求是“把调度系统从 crontab shell 脚本迁走”。当时团队里有两位工程师一位主张上 Airflow另一位坚持用 Azkaban。争论持续了三天最后我们没选任何现成方案——而是花了一下午把 Azkaban-3.51.0 源码拉下来本地编译、改配置、启服务、跑通一个带 Hive 和 Spark 任务的 pipeline全程没碰 Docker也没连外部 MySQL。结果第二天那位 Airflow 拥趸就默默删掉了他刚搭好的 Helm Chart。这不是反技术而是真实场景倒逼出的判断Azkaban 的核心价值从来不在“多先进”而在于极简的部署契约——它只要求三样东西一个能跑 Java 的环境、一个可写的磁盘路径、一个能通信的数据库哪怕只是 H2。它不依赖 ZooKeeper 做协调不强制要求 Kubernetes 集群不把 DAG 定义耦合进 Python SDK甚至不强制你写 YAML。它就是一个 Web UI 一个 Executor Server 一套基于 SQL 的元数据存储三者之间只靠 HTTP 和 JDBC 连接。这种“克制”让它在测试环境快速验证、离线数仓小集群冷启动、甚至客户现场无公网隔离网络中依然保持着不可替代的生存力。你看到热搜词里反复出现 “docker安装azkaban”、“azkaban-3.51.0 通过api进行操作”这恰恰说明大家不是不需要容器化而是先得搞懂它原生怎么活不是不想用 API而是得先让 Web 界面能点开、任务能提交、日志能刷出来。所有高级玩法都建立在“能跑通最朴素流程”的地基上。所以这篇内容不讲 Docker Compose 编排不讲 RESTful API 的 Swagger 文档生成也不讲如何对接 LDAP 认证——我们只做一件事用最原始、最可控、最贴近生产实际的方式把 Azkaban-3.51.0 在一台干净的 CentOS 7 或 Ubuntu 22.04 机器上从零装起来直到你能在浏览器里点击“Execute Flow”并看到 SUCCESS 状态。关键词里虽然空着但热搜词已经暴露了真实战场mysql 安装配置教程、tomcat 安装及配置教程、maven 安装与配置、python 环境变量的配置……这些不是干扰项而是 Azkaban 生存所依赖的底层栈。它不像 Node.js 应用那样自带运行时也不像 Python 工具那样 pip install 就完事。它的每个组件都必须和宿主环境达成明确的版本契约。接下来你要做的不是复制粘贴命令而是理解每一行命令背后Azkaban 在向操作系统索要什么权限、什么路径、什么端口、什么类库版本。1.1 Azkaban 的“三体结构”Web Server、Executor Server 与 Database 的共生逻辑Azkaban 不是一个单体进程而是一个由三个独立角色组成的协作体它们之间没有主从之分只有职责划分Azkaban Web Server提供用户界面、项目管理、权限控制、执行触发入口。它本身不执行任何任务只负责“发号施令”和“展示结果”。它需要一个 Web 容器默认内嵌 Jetty但生产环境强烈建议外挂 Tomcat需要连接数据库读取项目/用户/执行历史需要能访问 Executor Server 的 HTTP 接口来下发任务。Azkaban Executor Server真正干活的“工人”。它监听 Web Server 发来的执行请求拉取对应项目的 job 文件按依赖顺序执行 Shell/Java/Hive/Spark 等类型的任务并将 stdout/stderr 和状态实时回传给 Web Server。它也需要连接同一个数据库用于上报执行状态、心跳、日志元信息。Database三者的“共享记忆中枢”。它不存储业务数据只存 Azkaban 自身的元数据用户账号密码明文或加密、项目 ZIP 包的二进制快照、Flow 定义、Job 依赖关系、每次执行的 ID、开始时间、结束时间、状态SUCCEEDED/FAILED/KILLED、日志文件的存储路径等。没有它Web 和 Executor 就是两个失联的哑巴。这三者的关系不能简单理解为“客户端-服务端”。更准确地说是Web Server 是调度大脑Executor Server 是执行四肢Database 是共同的脊髓神经节。它们必须使用完全相同的数据库连接参数URL、用户名、密码、驱动类否则会出现“Web 上能看到项目但点执行就报错找不到 flow”它们的azkaban.properties配置文件中database.type、database.host、database.port、database.database等字段必须一字不差更重要的是数据库的初始化脚本必须由 Web Server 执行一次且仅此一次——这是很多初学者卡住的第一道墙Executor 启动后疯狂报Table azkaban.executors doesnt exist却不知道该去哪执行建表语句。提示Azkaban 官方包里自带create-all-sql-*.sql脚本但它不是给你直接 mysql -u root -p xxx.sql 用的。它必须由 Web Server 在首次启动时通过其内置的数据库初始化模块自动执行。如果你手动执行了后续 Web Server 启动会因检测到表已存在而跳过初始化导致部分关键视图或存储过程缺失最终表现为权限管理失效或执行历史无法查询。1.2 为什么坚决不推荐“一键 Docker 安装”作为入门路径我见过太多人在 Docker Hub 搜到azkaban-web:3.51.0镜像docker run -d -p 8081:8081 azkaban-web之后浏览器打开http://localhost:8081看到登录页就以为“装好了”。然后兴冲冲上传一个hive.job点击执行页面卡在“Submitting…” 十分钟F12 看 Network发现/executor接口 500 Internal Error。查日志全是Connection refused to http://localhost:12321—— 因为 Executor 根本没起或者起了但没暴露端口或者 Web Server 的配置里写的executor.port12321而 Docker 容器内部网络和宿主机 localhost 并不互通。Docker 的本质是进程隔离与环境封装但它不解决配置契约问题。Azkaban 的 Web 和 Executor 必须通过网络互相发现这个发现机制默认是硬编码的localhost而 Docker 容器里的localhost指向的是容器自身不是宿主机更不是另一个容器。要让它们通信你必须使用--network host模式放弃容器隔离退化为普通进程或者用docker-compose.yml显式定义 service 间依赖和extra_hosts或者修改azkaban.properties中的executor.port和executor.host为容器名如azkaban-executor或者启用 Azkaban 的 Executor Discovery 机制让 Web Server 主动去数据库查注册的 Executor 列表。以上每一种都需要你先理解 Azkaban 的通信模型。而绝大多数“Docker 一键安装”教程只会告诉你docker-compose up -d然后让你祈祷奇迹发生。当奇迹没发生时你面对的是一堆java.net.ConnectException却不知道该去改哪个配置文件、重启哪个容器、清哪个缓存。所以本文选择“裸机安装”路线不是守旧而是为了把所有隐性依赖显性化。当你亲手解压azkaban-web-server-3.51.0.tar.gz编辑conf/azkaban.propertieschmod x bin/start-web.sh再./bin/start-web.sh你会清晰地看到启动脚本里JAVA_HOME是否生效conf/目录下azkaban-users.xml是否被正确加载日志里Starting Jetty Server on port 8081是否出现ps aux | grep java是否真有一个-Dserver.port8081的进程。这种“看得见、摸得着、改得动”的掌控感是任何黑盒 Docker 镜像都无法提供的。它让你在后续遇到问题时能精准定位到是 Java 版本不对、是 MySQL 驱动 jar 包没放对位置、还是web.xml里 context-param 的azkaban.name写错了大小写。2. 环境准备不是“装软件”而是构建一个受控的 Java 生态沙箱Azkaban-3.51.0 是一个典型的 Java EE 风格应用它对运行时环境的要求非常具体且不容妥协。网上很多教程说“JDK 8 or later”这是严重误导。Azkaban 3.x 系列的源码编译目标是 Java 8其所有依赖库包括 Guava、Jetty、HikariCP的字节码版本都是52.0Java 8。如果你强行用 JDK 11 或 JDK 17 启动会遇到java.lang.UnsupportedClassVersionError错误信息里会明确写出Unsupported major.minor version 52.0。这不是兼容性问题是字节码规范的硬性门槛。同样“MySQL 5.7 or later” 也是模糊表述。Azkaban 3.51.0 的 JDBC 连接字符串默认使用useSSLfalseserverTimezoneUTC参数这在 MySQL 5.7.22 之后才被官方驱动 fully supported。如果你用 MySQL 5.6或者用了一个老版本的mysql-connector-java-5.1.47.jar就会在 Web Server 启动时报The server time zone value XXX is unrecognized然后整个初始化流程中断数据库表一个都建不起来。所以环境准备不是罗列一堆apt install命令而是为 Azkaban 构建一个精确匹配的、可复现的、隔离的 Java 生态沙箱。以下是我在生产环境验证过的最小可行组合以 Ubuntu 22.04 为例CentOS 7 同理仅包管理器命令不同2.1 JDK 8u292为什么必须是这个特定更新版OpenJDK 8 有多个发行版Oracle JDK、OpenJDK from Ubuntu repo、Adoptium Temurin、Zulu。它们在 JVM 参数默认值、GC 算法实现细节、甚至java -version输出格式上都有微小差异。Azkaban 的启动脚本bin/start-web.sh里有一段关键逻辑# Check for java if [ -z $JAVA_HOME ]; then JAVAwhich java if [ -z $JAVA ]; then echo Error: JAVA_HOME is not set and java could not be found. exit 1 fi JAVA_HOMEdirname $JAVA JAVA_HOMEdirname $JAVA_HOME fi这段代码试图从which java的路径反推JAVA_HOME。如果JAVA_HOME没设它会取dirname (dirname $(which java))。在 Ubuntu 22.04 的openjdk-8-jre-headless包中which java返回/usr/bin/javadirname /usr/bin/java是/usr/bindirname /usr/bin是/usr于是JAVA_HOME被设为/usr。但/usr下根本没有jre/lib/rt.jar导致启动失败。而 Adoptium Temurin 8u292-jdk 的安装结构是/home/user/jdk-8u292-jdk/which java返回/home/user/jdk-8u292-jdk/bin/javadirname嵌套后得到/home/user/jdk-8u292-jdk这才是正确的JAVA_HOME。因此我强烈推荐下载 Adoptium Temurin 8u292-jdkLTS 版本长期安全更新支持解压到固定路径例如/opt/java/jdk8u292然后在~/.bashrc中永久设置export JAVA_HOME/opt/java/jdk8u292 export PATH$JAVA_HOME/bin:$PATH验证方式不是java -version而是$JAVA_HOME/bin/java -version # 输出应为openjdk version 1.8.0_292 # OpenJDK Runtime Environment (Temurin)(build 1.8.0_292-b10) # OpenJDK 64-Bit Server VM (Temurin)(build 25.292-b10, mixed mode) # 并确认 rt.jar 存在 ls $JAVA_HOME/jre/lib/rt.jar # /opt/java/jdk8u292/jre/lib/rt.jar注意不要用sudo apt install openjdk-8-jdk。Ubuntu 22.04 默认源里的 openjdk-8-jdk 是 8u292 的一个变种但其JAVA_HOME推导逻辑已被 Ubuntu 补丁修改与 Azkaban 脚本不兼容。必须用 Adoptium 官方二进制包。2.2 MySQL 5.7.39为什么版本号要精确到小版本Azkaban 3.51.0 的数据库初始化脚本sql/create-all-sql-3.51.0.sql中有一段创建execution_jobs表的 DDLCREATE TABLE execution_jobs ( exec_id INT NOT NULL, job_name VARCHAR(128) NOT NULL, start_time BIGINT, end_time BIGINT, status TINYINT, input_params TEXT, attempt INT DEFAULT 0, PRIMARY KEY (exec_id, job_name, attempt), INDEX exec_id_index (exec_id), INDEX job_name_index (job_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci;注意ENGINEInnoDB和CHARSETutf8mb4。在 MySQL 5.7.39 之前utf8mb4字符集的默认排序规则collation是utf8mb4_general_ci而 Azkaban 的某些查询如SELECT * FROM projects WHERE name ?在utf8mb4_unicode_ci下才能正确处理中文、emoji 等四字节字符的比较。如果数据库初始化时用了utf8mb4_general_ci后续上传含中文项目名的 ZIP 包Web UI 会显示乱码甚至导致project_id查询失败。因此安装 MySQL 5.7 时必须在/etc/mysql/mysql.conf.d/mysqld.cnf中显式指定[mysqld] character-set-server utf8mb4 collation-server utf8mb4_unicode_ci default-storage-engine InnoDB然后重启 MySQL并创建数据库时指定字符集CREATE DATABASE azkaban DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;验证方式SHOW CREATE DATABASE azkaban; -- 输出应包含DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci USE azkaban; SHOW VARIABLES LIKE character_set%; SHOW VARIABLES LIKE collation%; -- 所有相关变量都应为 utf8mb4 和 utf8mb4_unicode_ci2.3 Maven 3.6.3编译源码而非下载二进制包的底层逻辑Azkaban 官网下载页http://azkaban.github.io/downloads.html提供的是预编译的tar.gz包。但这些包是用 Maven 3.6.3 JDK 8u292 在 CentOS 7 上编译的。如果你直接下载会遇到两个隐藏风险包内lib/目录下的mysql-connector-java-5.1.49.jar是编译时打包进去的但它的useSSL参数在 MySQL 5.7.39 上表现不稳定azkaban-web-server-3.51.0.jar的 MANIFEST.MF 里Class-Path引用的 jar 包路径是编译机器上的绝对路径虽然不影响运行但会污染你的CLASSPATH环境变量。所以我推荐的“纯净安装”路径是下载 Azkaban 3.51.0 源码用你自己的 Maven 3.6.3 在本地编译。这样你能完全掌控所有依赖的版本和路径。下载源码wget https://github.com/azkaban/azkaban/archive/refs/tags/3.51.0.tar.gz tar -xzf 3.51.0.tar.gz cd azkaban-3.51.0安装 Maven 3.6.3同样推荐 Adoptium Temurin 提供的二进制包解压到/opt/maven/apache-maven-3.6.3设置MAVEN_HOME和PATH。编译前必须修改pom.xml中的 MySQL 驱动版本。找到mysql.version标签将其从5.1.49改为8.0.28这是 MySQL 5.7.39 官方推荐的最新兼容驱动mysql.version8.0.28/mysql.version然后执行mvn clean package -DskipTests -P compile-with-hadoop-2.7-P compile-with-hadoop-2.7是关键参数。Azkaban 3.51.0 默认编译目标是 Hadoop 2.7.x如果你的集群是 Hadoop 3.x这里要换成-P compile-with-hadoop-3.0。编译完成后生成的包在azkaban-web-server/target/和azkaban-executor-server/target/目录下分别是azkaban-web-server-3.51.0.jar和azkaban-executor-server-3.51.0.jar。提示编译过程会下载大量依赖约 1.2GB请确保 Maven 的settings.xml配置了阿里云镜像源https://maven.aliyun.com/repository/public否则可能超时失败。编译耗时约 15 分钟CPU 占用率很高建议关闭其他应用。3. 核心配置详解azkaban.properties里每一行都是一个契约Azkaban 的灵魂不在代码而在配置文件。conf/azkaban.properties是 Web Server 和 Executor Server 的“宪法”它定义了二者如何与外界交互、如何与彼此通信、如何与数据库对话。网上很多教程把这份文件当作黑盒只告诉你“把 database.host 改成你的 IP”结果改完还是连不上。这是因为这份文件里的每一个属性都不是孤立的而是与其他属性、与操作系统环境、与数据库状态构成一个强约束的契约体系。以下是我从生产环境提炼出的、必须逐字核对的 12 个核心配置项以及它们背后的“为什么”。3.1 数据库连接database.*系列配置的连锁反应# 1. 数据库类型必须是 mysql不能是 mariadb 或 percona database.typemysql # 2. 数据库主机必须是 Executor Server 能 ping 通的地址 # 如果 Executor 和 Web 在同一台机器用 127.0.0.1不要用 localhostDNS 解析慢 database.host127.0.0.1 # 3. 数据库端口MySQL 默认 3306但如果你改了这里必须同步 database.port3306 # 4. 数据库名必须和你 CREATE DATABASE 时的名字完全一致区分大小写 database.databaseazkaban # 5. 数据库用户名必须有 azkaban 数据库的 ALL PRIVILEGES database.usernameazkaban_user # 6. 数据库密码明文存储生产环境建议用 MySQL 8.0 的 caching_sha2_password 插件加密 database.passwordyour_secure_password # 7. JDBC URL这是最关键的契约必须包含 useSSLfalse 和 serverTimezoneUTC # 缺少任何一个都会导致连接失败或时区错误 database.drivercom.mysql.cj.jdbc.Driver database.urljdbc:mysql://127.0.0.1:3306/azkaban?useSSLfalseserverTimezoneUTCallowPublicKeyRetrievaltrue # 8. MySQL 驱动 JAR 包路径必须指向你编译时指定的 mysql-connector-java-8.0.28.jar # 如果用官网二进制包这个路径是 lib/mysql-connector-java-5.1.49.jar database.mysql.driver.path/opt/azkaban/lib/mysql-connector-java-8.0.28.jar这 8 行配置构成了一个闭环。database.url里的127.0.0.1:3306必须和database.host/database.port一致database.database必须和 URL 里的/azkaban一致database.mysql.driver.path指向的 JAR 包其com.mysql.cj.jdbc.Driver类必须存在且版本必须和database.url的参数兼容。验证方法在 Web Server 启动前先手动测试 JDBC 连接cd /opt/azkaban/web-server $JAVA_HOME/bin/java -cp lib/*:conf/ com.mysql.cj.jdbc.Driver \ jdbc:mysql://127.0.0.1:3306/azkaban?useSSLfalseserverTimezoneUTC \ azkaban_user your_secure_password如果输出com.mysql.cj.jdbc.Driver的类信息说明驱动和 URL 都没问题。如果报ClassNotFoundException说明database.mysql.driver.path错了如果报Access denied说明用户名密码错如果报The server time zone value CST is unrecognized说明serverTimezoneUTC缺失。3.2 Web Server 专属配置jetty.*与web.*的边界# 9. Web Server 的监听端口生产环境建议避开 8080常被 Tomcat 占用 jetty.maxThreads25 jetty.ssl.port8443 jetty.port8081 # 10. Web Server 的上下文路径决定你浏览器访问的 URL # 如果设为 /azkaban则必须访问 http://host:8081/azkaban # 如果设为 /则直接访问 http://host:8081 web.context.path/ # 11. Web Server 的名称会显示在页面标题和日志里 # 必须和 Executor Server 的 azkaban.name 一致否则 Executor 注册失败 azkaban.nameazkaban-web-server # 12. Web Server 的时区必须和 database.url 的 serverTimezone 一致 # 否则执行历史的时间戳会错乱 web.timezone.idUTCjetty.port8081和web.context.path/共同决定了你的访问入口。很多人改了jetty.port却忘了检查防火墙sudo ufw allow 8081 # 或者 CentOS 7: sudo firewall-cmd --permanent --add-port8081/tcp sudo firewall-cmd --reloadazkaban.nameazkaban-web-server这一行极其重要。Executor Server 启动时会向数据库的executors表插入一条记录其中active字段为truehost字段为本机 IPport字段为executor.port而name字段就是它读取的azkaban.name属性。Web Server 在执行 Flow 时会查询executors表找name匹配且activetrue的 Executor。如果 Web Server 的azkaban.name是azkaban-web-server而 Executor Server 的azkaban.name是my-executor那么 Web Server 永远找不到可用的 Executor执行按钮永远是灰色的。3.3 Executor Server 专属配置executor.*的心跳与负载# 13. Executor Server 的监听端口必须和 Web Server 的 executor.port 一致 executor.port12321 # 14. Executor Server 的名称必须和 Web Server 的 azkaban.name 一致 # 这是两者建立信任的唯一标识 azkaban.nameazkaban-web-server # 15. Executor Server 的最大并发任务数根据机器 CPU 核数设置 # 公式max_threads (CPU 核数 * 2) 1 executor.maxThreads9 # 16. Executor Server 的工作目录所有 job 的临时文件、日志都放这里 # 必须是绝对路径且 azkaban 用户对该路径有读写权限 executor.flow.working.dir/opt/azkaban/executor/executions # 17. Executor Server 的日志级别生产环境建议 INFO调试时可调为 DEBUG executor.logger.levelINFOexecutor.port12321是 Web Server 和 Executor 通信的“电话号码”。Web Server 的azkaban.properties里也有一行executor.port12321它告诉 Web Server“去 12321 端口找 Executor”。如果 Executor Server 实际监听的是 12322或者防火墙拦住了 12321Web Server 就会报Failed to connect to executor at http://127.0.0.1:12321。executor.flow.working.dir是一个易被忽视的坑。Azkaban 执行一个 Flow 时会把这个 Flow 对应的 ZIP 包解压到这个目录下的一个随机 UUID 子目录里然后依次执行里面的.job文件。如果这个目录空间不足比如/opt分区只有 10GB或者权限不对比如chown root:root /opt/azkaban/executor/executionsExecutor 启动时会报java.io.IOException: Permission denied然后拒绝注册。提示executor.flow.working.dir的父目录/opt/azkaban/executor/必须存在且chown -R azkaban:azkaban /opt/azkaban/executor/。Azkaban 进程必须以azkaban用户身份运行而不是root。这是安全最佳实践也是避免Permission denied的根本方法。4. 启动与验证从start-web.sh到第一个 SUCCESS 的完整链路配置文件写完不等于万事大吉。Azkaban 的启动是一个有严格时序的多阶段过程任何一环出错都会导致后续步骤失败。网上很多教程只告诉你./bin/start-web.sh然后./bin/start-executor.sh就结束了。但真实世界里你需要观察日志、理解状态、主动干预。4.1 Web Server 启动初始化数据库是“一次性仪式”执行./bin/start-web.sh后不要立刻去浏览器访问。先看日志tail -f logs/webserver.log你期望看到的关键日志序列是INFO [Server] Starting Jetty Server on port 8081 INFO [DatabaseUtils] Initializing database... INFO [DatabaseUtils] Executing create-all-sql-3.51.0.sql INFO [DatabaseUtils] Creating table projects... INFO [DatabaseUtils] Creating table executors... INFO [DatabaseUtils] Creating table execution_flows... INFO [DatabaseUtils] Creating table execution_jobs... INFO [DatabaseUtils] Creating table user_roles... INFO [DatabaseUtils] Creating table project_events... INFO [DatabaseUtils] Creating table project_permissions... INFO [DatabaseUtils] Creating table project_files... INFO [DatabaseUtils] Creating table project_versions... INFO [DatabaseUtils] Creating table project_properties... INFO [DatabaseUtils] Creating table project_logs... INFO [DatabaseUtils] Creating table project_log_chunks... INFO [DatabaseUtils] Creating table project_log_metadata... INFO [DatabaseUtils] Creating table project_log_chunks_archive... INFO [DatabaseUtils] Creating table project_log_metadata_archive... INFO [DatabaseUtils] Creating table project_log_chunks_archive_history... INFO [DatabaseUtils] Creating table project_log_metadata_archive_history... INFO [DatabaseUtils] Database initialization completed successfully. INFO [Server] Started Jetty Server on port 8081如果日志卡在Executing create-all-sql-3.51.0.sql或者出现ERROR [DatabaseUtils] Failed to execute SQL script说明数据库连接或权限有问题。此时不要 CtrlC 强制退出因为 Web Server 进程还在运行它会不断重试初始化占用数据库连接。应该ps aux | grep webserver找到进程 PIDkill -15 PID优雅停止检查logs/webserver.log最后 100 行定位具体哪条 SQL 失败登录 MySQL手动执行那条 SQL看报什么错通常是Table azkaban.xxx doesnt exist说明前面的建表语句失败了需要清空数据库重来。一旦看到Database initialization completed successfully.就可以curl http://127.0.0.1:8081测试。如果返回 HTML 页面包含titleAzkaban/title说明 Web Server 启动成功。4.2 Executor Server 启动注册与心跳的双向确认Web Server 启动成功后再启动 Executor Servercd /opt/azkaban/executor-server ./bin/start-executor.sh同样看日志tail -f logs/executor.log关键日志INFO [ExecutorServer] Starting Executor Server on port 12321 INFO [ExecutorServer] Registering executor with web server... INFO [ExecutorServer] Registered executor with web server successfully. INFO [ExecutorServer] Starting heartbeat thread... INFO [ExecutorServer] Heartbeat sent to web server. INFO [ExecutorServer] Heartbeat received from web server.Registered executor with web server successfully.是黄金信号。它意味着 Executor 已成功向数据库executors表插入了自己的记录并且 Web Server 的心跳线程检测到了它。验证方式登录 MySQL查executors表USE azkaban; SELECT * FROM executors; -- 应该有一条记录host 是你的机器 IPport 是 12321active 是 1name 是 azkaban-web-server如果active是 0说明 Executor 注册失败原因通常是azkaban.name不匹配或者 Web Server 没在运行。4.3 创建第一个 Flow从 ZIP 上传到 SUCCESS 的端到端验证现在打开浏览器http://your-server-ip:8081默认用户名/密码是azkaban/azkaban来自conf/azkaban-users.xml。创建项目点击Create Project输入test-project描述随便写点击Create。上传 ZIP准备一个最简单的 Flow ZIP 包。在本地新建文件夹test-flow里面放一个test.job文件# test-flow/test.job typecommand commandecho Hello from Azkaban! Current time: $(date)然后zip -r test-flow.zip test-flow/。上传并执行在 Web UI 的test-project页面点击Upload选择test-flow.zip上传成功后点击test-flow再点击Execute Flow。此时页面会跳转到执行详情页状态从PREPARING-RUNNING-SUCCEEDED。点击View Log你应该看到INFO - Starting job test at 1717023456000 INFO - Executing command: echo Hello from Azkaban! Current time: $(date) INFO - Command completed successfully INFO - Job test finished with status SUCCEEDED如果卡在PREPARING说明 Executor 没注册成功如果卡在RUNNING且日志为空说明executor.flow.working.dir权限不对如果报Command echo not found说明 Executor 的PATH环境变量没继承好需要在conf/azkaban.properties里加executor.env.PATH/usr/local/bin:/usr/bin:/bin提示Azkaban 的typecommandjob默认是在 Executor 的 shell 环境下执行的。这个 shell 环境的PATH是由启动start-executor.sh的用户azkaban的~/.bashrc决定的。如果你的azkaban用户没有配置PATH或者start-executor.sh是用sudo -u azkaban ./bin/start-executor.sh启动的它可能不会加载~/.bashrc。最稳妥的办法就是在azkaban.properties里显式设置executor.env.PATH。5. 常见故障排查从Connection refused到No such file or directory的实战路径即使严格按照上述步骤操作你仍可能遇到各种“意料之外”的错误。这些错误不是配置失误而是 Azkaban 与 Linux 系统、Java 运行时、MySQL 驱动之间微妙的交互结果。以下是我在线上环境处理过的 5 个