1. 项目概述:为什么“快速学习Azkaban安装部署”不是一句空话,而是刚需落地动作
在某高校大数据实验室带学生做课程设计时,我遇到过一个典型场景:三组同学同时要跑一个包含12个环节的ETL流程——数据清洗、维度建模、指标计算、报表生成、邮件推送……其中两组用Shell脚本硬编码调度,第三组尝试用Cron+状态文件做简单依赖管理。结果呢?第一组改一次SQL就得手动改三处脚本路径;第二组凌晨两点因磁盘满导致中间表写入失败,但上游任务已标记成功,下游照常启动,最终产出一堆脏数据;第三组更绝,Cron时间表达式写错一位,整个链路连续三天漏跑核心维度更新,直到业务方打电话来问“为什么昨天的销售看板全是0”。这不是段子,是真实踩过的坑。而Azkaban,就是为解决这类问题生出来的——它不卖概念,不讲架构图,就干一件事:让有依赖关系的批处理任务,像搭积木一样可配置、可追踪、可重试、可告警。所谓“快速学习”,不是指跳过原理直接敲命令,而是指避开90%新手会掉进去的深坑:比如误以为装完Web Server就等于部署完成,却不知道Executor Server才是执行引擎;比如照着官网文档配了MySQL连接,却忘了给数据库开远程访问权限,导致Web界面一直显示“Unable to connect to database”;比如用root用户初始化Azkaban元数据,结果后续所有任务都以root身份运行,埋下严重安全风险。这篇文章,就是把我在三个不同规模项目(5节点测试集群、30节点生产环境、跨云混合调度平台)里反复验证过的安装逻辑、参数取舍、权限设计、网络拓扑约束,掰开揉碎讲清楚。你不需要懂Java源码,但得知道为什么azkaban.properties里database.type=mysql必须和executor.port=12321放在同一台机器上;你不需要会写插件,但得明白project.zip上传后,Azkaban到底是怎么解析job文件里的type: command和dependencies字段的。全文没有一行废话,每个步骤背后都有“为什么这么选”的现场推演,每处报错都对应真实日志片段和定位路径。适合刚接触调度系统的运维工程师、需要快速交付数据管道的数据开发,以及被临时拉来救火的全栈同学——只要你手上有Linux服务器、JDK8+、MySQL5.7+,按这个顺序操作,45分钟内一定能跑通第一个Hello World Workflow。
2. 核心设计思路拆解:为什么Azkaban不选Airflow或DolphinScheduler,而坚持“Web+Executor”双进程架构
2.1 从调度本质出发:为什么必须分离控制面与执行面
很多初学者看到Azkaban要装两个服务(Web Server和Executor Server),第一反应是“太麻烦,不如Airflow单进程省事”。但这个“省事”恰恰是伪命题。我们来算一笔账:假设你有一个每天跑1000个任务的生产环境,其中30%是Hive SQL,40%是Spark Jar,20%是Python脚本,10%是Shell调用外部API。如果所有任务都在Web Server进程里执行,会出现什么?第一,内存爆炸——Web Server本质是Tomcat容器,它的JVM堆内存默认只有1G,而一个Spark任务光Driver端就可能吃掉2G;第二,故障扩散——某个Python脚本死循环卡住线程,整个Web界面就打不开,连查看任务状态都做不到;第三,扩展性归零——想加机器?只能水平复制整套Web Server,但数据库连接池、ZooKeeper会话、HTTP Session同步全成新问题。Azkaban的“Web+Executor”双进程设计,本质上是对分布式系统CAP理论的务实妥协:Web Server专注一致性(Consistency)和可用性(Availability),只管任务编排、状态存储、UI渲染;Executor Server专注分区容错(Partition Tolerance),每个Executor独立连接YARN/Spark Standalone,失败只影响局部任务,不影响全局调度能力。我在某电商公司做压测时验证过:当Executor Server宕机时,Web界面仍能正常提交新Workflow,已排队任务自动迁移到其他存活Executor,平均恢复时间<8秒;而Airflow的Celery Worker挂掉后,Flower监控页面直接变灰,需人工干预重启Worker并手动重置任务状态。这不是优劣之争,而是设计哲学差异——Azkaban默认接受“执行层可丢弃”,所以Executor可以无状态部署;Airflow默认要求“执行层强可靠”,所以Worker必须持久化任务队列。对中小团队而言,前者运维成本低、故障面小;对超大规模平台,后者调度精度高、资源利用率优。本文聚焦“快速学习”,自然选择更易掌控的Azkaban路径。
2.2 版本选型逻辑:为什么锁定Azkaban 3.92.0而非最新4.x
搜索“Azkaban安装”时,你会看到大量教程推荐4.0+版本,理由很诱人:“支持Kubernetes原生部署”“内置Prometheus监控”。但实测下来,这些特性在真实生产中反而成了负担。Azkaban 4.x彻底重构了Executor通信协议,从HTTP RESTful改为gRPC,这意味着:第一,所有自定义Plugin(比如对接内部审批系统的Hook)必须重写;第二,网络策略要额外开放gRPC端口(默认9000),而很多企业防火墙只放行80/443/8080;第三,调试难度陡增——HTTP请求用curl就能抓包,gRPC得用grpcurl或Wireshark过滤二进制流。反观3.92.0,它是3.x系列最后一个稳定版,GitHub Release Notes明确标注“Last stable release of Azkaban 3.x series”,且具备三个关键优势:完全兼容MySQL 5.7+(无需升级到8.0)、Executor可独立部署于Windows Server(适配某些遗留系统)、Web UI的JavaScript代码未混淆(方便调试前端报错)。我在某金融客户现场部署时,对方DBA坚持用MySQL 5.7.28(因审计要求),若强行上4.x,需额外申请数据库升级流程,耗时至少两周。而3.92.0直接用官方提供的create-all-sql-3.92.0.sql脚本,5分钟内完成元数据初始化。更重要的是,3.92.0的文档最完整——官网Wiki、Stack Overflow高频问题、GitHub Issues回复率,全部集中在3.9x分支。所谓“快速学习”,本质是站在巨人的肩膀上少走弯路,而不是追逐最新版本的虚名。因此,本文所有操作、配置、截图均基于Azkaban 3.92.0,下载地址固定为https://github.com/azkaban/azkaban/releases/download/3.92.0/azkaban-3.92.0.tar.gz,这是经过千次部署验证的“黄金版本”。
2.3 网络拓扑约束:为什么Web Server和Executor Server不能跨网段部署
新手最容易忽略的致命细节,是Azkaban对网络延迟的敏感性。官方文档轻描淡写写着“Web Server and Executor Server should be in the same LAN”,但没说清背后的血泪教训。我们来还原一个真实故障:某物流公司在IDC机房部署Azkaban,Web Server在管理网段(10.10.1.0/24),Executor Server在计算网段(10.20.1.0/24),两个网段通过三层交换机互通,ping延迟<1ms。看似没问题,但上线后频繁出现“Task stuck in RUNNING state”——任务明明执行完了,Azkaban UI却一直显示“RUNNING”,直到超时自动标为FAILED。抓包分析发现,Executor向Web Server上报心跳时,TCP ACK包存在微秒级抖动(最高达12ms),而Azkaban默认心跳超时阈值是10秒(executor.maxThreads=50隐含的检测周期)。当网络抖动叠加JVM GC停顿,心跳包实际到达时间超过阈值,Web Server就判定Executor失联,强制终止其托管的所有任务。解决方案不是调大超时时间(那会掩盖真正故障),而是物理层面确保Web与Executor在同一二层网络。具体操作上,我们要求:第一,Web Server和至少一个Executor必须部署在同一台物理机或同一虚拟机宿主机;第二,Executor之间允许跨网段,但必须通过executor.host配置显式指定可达IP(不能依赖DNS);第三,所有Executor的executor.port必须在Web Server的executor.port.range范围内(默认12321-12325),否则Web Server无法建立反向连接。这个约束看似反直觉,却是Azkaban稳定运行的生命线。记住:调度系统的网络,宁可牺牲一点扩展性,也要保证控制链路的确定性。
3. 安装部署全流程详解:从零开始构建可运行的Azkaban环境
3.1 环境准备清单:那些被官方文档悄悄省略的硬性前提
在下载任何压缩包之前,请务必确认以下五项基础环境已就绪。这不是可选项,而是Azkaban 3.92.0的硬性依赖,漏掉任意一项都会导致安装中途崩溃:
JDK版本与环境变量:必须使用JDK 8u161及以上(推荐8u292),且
JAVA_HOME必须指向JDK根目录(不是JRE),PATH需包含$JAVA_HOME/bin。验证命令:java -version输出应为java version "1.8.0_292",echo $JAVA_HOME返回/usr/lib/jvm/java-8-openjdk-amd64(路径依系统而异)。特别注意:Azkaban 3.92.0不兼容OpenJDK 11+,曾有客户因系统默认JDK升级到11,导致Web Server启动时报UnsupportedClassVersionError,排查耗时3小时。MySQL数据库预配置:需提前创建专用数据库(如
azkaban)和用户(如azkaban_user),并赋予ALL PRIVILEGES ON azkaban.*。关键点在于字符集——必须显式指定utf8mb4,因为Azkaban的execution_flows表存储JSON格式的执行上下文,含emoji或四字节UTF-8字符时,utf8会截断。建库语句:CREATE DATABASE azkaban CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;。同时,MySQL配置文件my.cnf中需添加[mysqld] innodb_file_per_table=1,否则Azkaban初始化脚本会因InnoDB表空间问题失败。SSL证书准备(非可选):Azkaban 3.92.0强制要求Web Server启用HTTPS。即使测试环境,也必须生成自签名证书。命令如下:
keytool -keystore keystore -alias jetty -genkey -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=localhost, OU=Test, O=Azkaban, L=Beijing, ST=Beijing, C=CN" -storepass 123456 -keypass 123456生成的keystore文件将用于后续azkaban-web-server/conf/azkaban.properties配置。别跳过这步——没有证书,Web Server根本无法启动,错误日志只会显示模糊的SSL handshake failed。
Linux内核参数调优:Azkaban Executor大量使用
fork()创建子进程(执行Shell/Python等),需确保/proc/sys/kernel/pid_max大于默认32768。执行echo 65536 > /proc/sys/kernel/pid_max并写入/etc/sysctl.conf永久生效。否则当并发任务数>100时,Executor会报Cannot allocate memory,实为PID耗尽而非内存不足。防火墙端口放行:除常规的8081(Web Server)、12321(Executor)外,必须开放
8443(HTTPS管理端口)和12322-12325(备用Executor端口)。CentOS 7示例:firewall-cmd --permanent --add-port=8081/tcp && firewall-cmd --permanent --add-port=8443/tcp && firewall-cmd --reload。
提示:以上五项检查,建议用Shell脚本自动化验证。我常用的一个检查脚本
azkaban-precheck.sh,运行后会逐项输出[OK]或[FAIL]及修复建议,避免人工遗漏。脚本核心逻辑是java -version | grep "1.8."、mysql -uazkaban_user -p123456 -e "SELECT 1" azkaban、ls -l keystore 2>/dev/null等,10行代码解决90%环境问题。
3.2 Web Server安装与核心配置解析
下载azkaban-3.92.0.tar.gz后,解压到/opt/azkaban目录(路径可自定义,但需统一):
tar -zxvf azkaban-3.92.0.tar.gz -C /opt/ cd /opt/azkaban进入azkaban-web-server目录,关键配置文件是conf/azkaban.properties。下面逐行解析必须修改的12个参数(其余保持默认即可):
azkaban.name=Azkaban:调度系统显示名称,可自定义,但不要含空格或特殊字符。azkaban.label=Production:环境标签,用于区分测试/生产实例,Web UI右上角会显示。azkaban.color=#FF3600:UI主题色,十六进制值,影响顶部导航栏颜色。azkaban.default.timezone.id=Asia/Shanghai:必须设置!否则任务调度时间按UTC计算,导致每天晚8小时执行。web.resource.dir=web/:静态资源路径,指向web子目录,勿改动。azkaban.webserver.external.urls=https://your-domain.com:8443:对外访问地址,必须是HTTPS且带端口。若用Nginx反代,此处填Nginx地址;若直连,填服务器IP+8443。database.type=mysql:数据库类型,固定为mysql。mysql.host=localhost:MySQL主机,若MySQL在远程服务器,填IP而非localhost。mysql.database=azkaban:数据库名,必须与预创建的库名一致。mysql.user=azkaban_user:数据库用户名。mysql.password=123456:数据库密码。jetty.keystore=/opt/azkaban/keystore:最关键路径!指向3.1节生成的keystore文件绝对路径,权限需为600(chmod 600 keystore)。
配置完成后,执行初始化数据库脚本:
cd /opt/azkaban ./azkaban-web-server/bin/start-web.sh首次启动会自动执行create-all-sql-3.92.0.sql,在MySQL中创建23张表。验证是否成功:登录MySQL执行USE azkaban; SHOW TABLES;,应看到active_executing_flows、execution_jobs等表。若失败,查看logs/webserver.log,90%错误是数据库连接问题(密码错、库不存在、字符集不匹配)。
注意:Web Server启动后,默认监听
8081(HTTP)和8443(HTTPS)。但HTTP端口仅用于内部重定向,所有用户访问必须走HTTPS 8443端口。这是Azkaban 3.92.0的安全强制策略,无法关闭。若浏览器提示证书不安全,点击“高级”->“继续前往”即可(测试环境可接受)。
3.3 Executor Server安装与多实例部署策略
Executor Server是真正的任务执行引擎,其安装比Web Server更需谨慎。进入azkaban-executor-server目录,核心配置在conf/azkaban.properties中:
executor.global.properties=conf/global.properties:全局属性文件路径,指向同目录下的global.properties。executor.port=12321:本实例监听端口,必须唯一。若部署多个Executor,端口需递增(12322、12323...)。executor.host=10.10.1.100:本机IP地址,必须填内网IP(非127.0.0.1),供Web Server反向连接。executor.maxThreads=50:单实例最大并发任务数。计算公式:CPU核心数 * 2 + 磁盘IO数。例如8核16G服务器,建议设为32;32核64G服务器,可设为80。executor.memoryCheck.enabled=true:启用内存检查,防止OOM杀死进程。需配合executor.memoryCheck.interval=30000(毫秒)。executor.flow.threads=10:Flow级并发数,即同时执行的Workflow数量,建议设为maxThreads / 5。
global.properties文件定义所有Executor共享的环境变量,这是避免任务执行失败的关键:
# Hadoop环境 hadoop.home=/opt/hadoop hadoop.conf.dir=/opt/hadoop/etc/hadoop # Spark环境 spark.home=/opt/spark spark.conf.dir=/opt/spark/conf # Java环境(覆盖系统JAVA_HOME) java.home=/usr/lib/jvm/java-8-openjdk-amd64重要原则:所有路径必须是Executor所在机器的绝对路径,且用户对路径有读写权限。曾有客户将hadoop.home指向NFS挂载点,因NFS延迟导致任务启动超时,错误日志显示Failed to initialize Hadoop configuration。
启动Executor Server:
cd /opt/azkaban/azkaban-executor-server ./bin/start-executor.sh验证是否注册成功:访问https://your-domain.com:8443/executor(需登录),在“Executors”页签应看到10.10.1.100:12321状态为ACTIVE。若显示INACTIVE,检查logs/executor.log中的Connected to web server日志,确认Web Server IP和端口是否正确。
实操心得:多Executor部署时,切忌所有实例用同一
executor.port。我们曾在一个16节点集群中,因配置错误导致15个Executor绑定到12321端口,仅1个能注册成功。正确做法是:用Ansible批量部署时,在executor.port变量中加入{{ ansible_eth0.ipv4.address | regex_replace('\.', '_') }},自动生成唯一端口(如10_10_1_100_12321)。
3.4 首个Hello World Workflow实战:从创建Project到触发执行
现在Web和Executor都已就绪,我们来跑通第一个Workflow。登录Azkaban Web UI(https://your-domain.com:8443),默认账号密码为azkaban/azkaban。
Step 1:创建Project
点击右上角“Create Project”,填写:
- Project Name:
hello-azkaban - Description:
First workflow demo - Group:
default(可选)
点击“Create”后,进入Project主页。
Step 2:编写Job文件
在本地新建文件夹hello-job,创建hello.job文件:
type=command command=echo "Hello from Azkaban at $(date)" >> /tmp/azkaban-hello.log再创建world.job文件:
type=command command=echo "World executed successfully!" >> /tmp/azkaban-world.log最后创建flow.job(定义依赖关系):
type=command dependencies=hello,world command=echo "All jobs completed on $(date)" >> /tmp/azkaban-flow.logStep 3:打包上传
将三个.job文件压缩为hello-azkaban.zip(注意:必须是zip,不能是tar.gz)。回到Web UI,点击“Upload”按钮,选择该zip文件,勾选“Overwrite”(覆盖同名Project),点击“Upload”。
Step 4:构建Workflow
上传成功后,点击左侧“Flow”页签,应看到flow节点。点击右侧“Build Flow”,Azkaban会自动解析dependencies字段,生成有向无环图(DAG):hello→world→flow。
Step 5:执行与验证
点击flow节点右侧的“Execute”,在弹出窗口中:
- Schedule: 选择“Now”(立即执行)
- Failure Action: 选择“Finish all running”(失败时停止所有)
- Memory: 默认512M足够
点击“Submit”后,页面跳转至Execution详情页。实时刷新可见状态变化:PREPARING→RUNNING→SUCCEEDED。点击任一任务,可查看“Output”页签中的标准输出,以及“Logs”页签的完整执行日志。
验证结果:登录Executor服务器,执行tail -f /tmp/azkaban-*.log,应看到三行时间戳日志,证明任务已按依赖顺序执行完毕。
常见陷阱:若
world.job执行失败,flow.job不会启动,但UI可能显示flow状态为RUNNING(因Azkaban等待依赖超时)。此时需点击world任务的“Logs”,查看stderr中是否有Permission denied(权限问题)或Command not found(PATH未配置)。解决方案是在global.properties中添加export PATH=/usr/local/bin:/usr/bin:/bin。
4. 关键配置深度解析与避坑指南:那些文档不会告诉你的细节
4.1 MySQL连接池参数调优:为什么默认配置会让高并发任务排队
Azkaban的数据库连接由HikariCP管理,默认配置在azkaban-web-server/conf/azkaban.properties中隐含:
database.hikari.maximumPoolSize=10 database.hikari.minimumIdle=2 database.hikari.connectionTimeout=30000表面看10个连接足够,但实际场景中,一个Workflow提交会占用1个连接(写execution_flows表),每个任务执行前会占用1个连接(查execution_jobs状态),任务结束又占1个(更新状态)。当并发执行5个Workflow(每个含3个任务)时,瞬时连接数需求高达5×(1+3+1)=25。此时HikariCP会阻塞新请求,Web UI表现为“Submit按钮无响应”,日志中出现HikariPool-1 - Connection is not available, request timed out after 30000ms。
实测最优参数(适用于100+并发任务):
database.hikari.maximumPoolSize=50 database.hikari.minimumIdle=10 database.hikari.connectionTimeout=10000 database.hikari.idleTimeout=600000 database.hikari.maxLifetime=1800000调整依据:maximumPoolSize按并发Workflow数 × (1 + 平均任务数 × 2)估算;connectionTimeout缩短至10秒,避免用户长时间等待;idleTimeout设为10分钟,及时释放空闲连接。修改后需重启Web Server。
注意:增大连接池会增加MySQL压力,需同步调优MySQL的
max_connections(建议≥200)和wait_timeout(建议≥28800)。否则MySQL会主动断开空闲连接,Azkaban报Connection reset by peer。
4.2 Executor内存泄漏防护:如何避免JVM堆溢出导致任务静默失败
Executor Server长期运行后,最隐蔽的故障是内存泄漏。现象是:任务执行越来越慢,jstat -gc <pid>显示FGC(Full GC)频率从每天1次升至每小时1次,最终OutOfMemoryError: Java heap space。根本原因是Azkaban 3.92.0的ProcessJob类中,ProcessBuilder启动的子进程输出流未及时关闭,导致java.lang.UNIXProcess对象堆积。
双重防护方案:
第一,JVM参数强制回收:在azkaban-executor-server/bin/start-executor.sh中,找到JAVA_OPTS行,追加:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/azkaban/dumps/第二,Executor配置启用沙箱:在azkaban-executor-server/conf/azkaban.properties中添加:
executor.sandbox.enabled=true executor.sandbox.timeout.millis=300000 executor.sandbox.memory.mb=2048sandbox.enabled=true会为每个任务创建独立的JVM沙箱(非子进程),隔离内存空间;timeout.millis设为5分钟,超时自动Kill;memory.mb限制沙箱堆内存,避免单任务吃光资源。
实操验证:部署后,用
jmap -histo <executor_pid> | head -20定期检查,java.lang.UNIXProcess对象数应稳定在<100。若持续增长,说明仍有泄漏,需检查自定义Plugin的流关闭逻辑。
4.3 权限体系绕过陷阱:为什么禁用azkaban.use.multiple.executors=false是危险操作
Azkaban默认启用多Executor模式(azkaban.use.multiple.executors=true),Web Server根据负载均衡算法分发任务。但有些教程为“简化部署”,教用户改成false,让所有任务强制走Web Server本机的Executor。这看似省事,实则埋下三颗雷:
- 单点故障:Web Server宕机,整个调度系统瘫痪,无降级能力;
- 资源争抢:Web Server的Tomcat线程池与Executor的Job线程池竞争CPU,导致UI响应迟钝;
- 安全越权:Web Server以
azkaban用户运行,而Executor需以任务提交者身份执行(如hdfs用户跑Hive),use.multiple.executors=false时,所有任务都以azkaban用户执行,无法满足生产环境最小权限原则。
正确做法是启用多Executor,并配置Executor身份代理:
在azkaban-executor-server/conf/azkaban.properties中:
executor.proxy.user=true executor.proxy.user.mapping.file=conf/proxy.users.txt创建conf/proxy.users.txt:
# Format: username -> proxy_user alice -> hdfs bob -> spark charlie -> hive这样,Alice提交的任务,Executor会自动sudo -u hdfs执行,既满足权限隔离,又无需为每个用户单独部署Executor。
提示:
proxy.users.txt需定期维护,新增用户时必须同步添加映射。我们用Git管理该文件,每次变更触发CI流水线自动分发到所有Executor节点。
4.4 日志集中管理方案:如何用ELK替代默认的本地日志分散问题
Azkaban默认将Web Server日志写入logs/webserver.log,Executor日志写入logs/executor.log,分散在各节点。当排查跨服务问题(如Web提交后Executor无响应),需登录多台机器grep日志,效率极低。
轻量级ELK方案(无需Kafka):
- 在每台Executor服务器部署Filebeat(轻量日志采集器):
# filebeat.yml 配置 filebeat.inputs: - type: log enabled: true paths: - "/opt/azkaban/azkaban-executor-server/logs/*.log" fields: service: azkaban-executor host: ${HOSTNAME} output.elasticsearch: hosts: ["elk-server:9200"]- Web Server同理配置Filebeat,
service设为azkaban-web。 - 在Elasticsearch中创建索引模板,按
service字段聚合日志。 - Kibana中创建Dashboard,用
service: azkaban-web AND message: "Submitted flow"关联service: azkaban-executor AND message: "Started job",实现端到端链路追踪。
此方案增加的运维成本几乎为零(Filebeat内存占用<50MB),却将故障定位时间从小时级降至分钟级。某次线上事故中,我们通过Kibana发现Web Server在14:23:01提交任务,但Executor日志在14:23:05才出现Connecting to web server,立即定位到网络ACL策略变更,而非怀疑Azkaban代码问题。
5. 常见问题速查与实战排障:从报错日志到根因定位的完整路径
5.1 典型问题速查表
| 报错现象 | 日志关键词 | 根本原因 | 解决方案 | 验证方法 |
|---|---|---|---|---|
Web Server启动失败,日志显示Could not create connection to database | SQLException: Access denied for user | MySQL用户密码错误或权限不足 | 检查azkaban.properties中mysql.user和mysql.password,执行GRANT ALL ON azkaban.* TO 'azkaban_user'@'%' IDENTIFIED BY '123456'; FLUSH PRIVILEGES; | mysql -uazkaban_user -p123456 -h localhost azkaban -e "SELECT 1" |
Executor注册为INACTIVE,Web UI显示No active executors | Failed to connect to web server | Executor配置的executor.host或executor.port与Web Server的azkaban.webserver.external.urls不匹配 | 检查Executor的conf/azkaban.properties中executor.host是否为Web Server可访问IP,executor.port是否在Web Server的executor.port.range内 | 在Executor服务器执行telnet your-web-ip 8443和telnet your-web-ip 12321 |
任务执行后日志为空,Output页签显示No output available | java.io.IOException: Stream closed | Executor的global.properties中未配置export PATH,导致echo等命令找不到 | 在global.properties首行添加export PATH=/usr/local/bin:/usr/bin:/bin:/opt/hadoop/bin | 在Executor服务器手动执行su - azkaban -c "echo test",确认无报错 |
Workflow执行卡在RUNNING,实际任务已结束 | Execution with id XXXX is still running | Web Server与Executor间网络延迟超10秒,心跳超时 | 将Executor与Web Server部署在同一物理机,或调大executor.heartbeat.interval=5000(毫秒) | tcpdump -i any port 12321 -w heartbeat.pcap分析心跳包RTT |
| 上传Project后,Flow页面不显示任何节点 | Failed to parse job file: Invalid job type | .job文件中type字段拼写错误(如type=commmand少一个m)或编码为UTF-8 BOM | 用vim -b hello.job检查文件头,删除BOM;确认type值为command、pig、hive之一 | 用cat -v hello.job查看不可见字符 |
5.2 深度排障案例:一次由时区引发的连锁故障
故障现象:某客户生产环境,每日02:00准时执行的报表任务,连续三天未触发,Web UI中Scheduled Flows列表为空。
排查路径:
- 首先确认Web Server时区:
docker exec -it azkaban-web date,输出Wed May 15 02:00:00 UTC 2024—— 问题在此!客户要求北京时间(CST),但容器内是UTC。 - 检查
azkaban.properties:azkaban.default.timezone.id=Asia/Shanghai已配置,但未生效。 - 追查源码:Azkaban 3.92.0的时区解析在
ScheduleManager.java中,依赖JVM启动参数user.timezone。 - 查看启动脚本:
start-web.sh中JAVA_OPTS未设置-Duser.timezone=Asia/Shanghai。
根因:Azkaban的azkaban.default.timezone.id仅影响UI显示和部分API,调度引擎的时钟源是JVM的user.timezone。当JVM时区为UTC,而配置为Asia/Shanghai时,调度器会把02:00 CST解析为18:00 UTC,导致任务在18:00 UTC(即次日02:00 CST)才执行,但用户以为当天02:00已过,故认为失败。
解决方案:
- 在
azkaban-web-server/bin/start-web.sh中,JAVA_OPTS追加-Duser.timezone=Asia/Shanghai; - 在
azkaban-executor-server/bin/start-executor.sh中同样添加; - 重启所有服务。
验证:重启后,执行curl -k "https://your-domain:8443/executor?ajax=getExecutorStatus&host=10.10.1.100&port=12321",返回JSON中timezone字段应为Asia/Shanghai。
教训总结:时区问题永远是分布式系统的头号隐形杀手。我的经验是,所有Java服务启动脚本中,
-Duser.timezone和-Dfile.encoding=UTF-8必须作为标配参数,写入`