Azkaban solo-server 部署实战:从解压到跑通第一个工作流
简介这是一份Azkaban单服务器版安装包已编译打包为tar.gz格式面向需要快速搭建任务调度环境的大数据开发、运维人员及初学者。包体约42.28MB已有256人浏览学习。压缩包解压后可直接使用省去编译环节适合小规模数据处理工作流的调度与管理。Azkaban提供直观的Web操作界面支持多项目管理、作业依赖编排、定时触发以及执行日志查看用户可基于此包快速部署单机环境完整实践从任务定义到运行监控的闭环流程。解压后可见bin、conf等目录其中包含服务器启动脚本、数据库初始化和核心配置文件便于按需修改端口与存储参数。该版本属于SNAPSHOT开发版功能完整度较高但如需生产级高可用建议后续迁移到集群模式。对希望掌握Hadoop生态任务调度、验证工作流逻辑或进行二次开发的开发者来说这份资源可直接用于本地测试与学习。1. 拿到 azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz 之后先别急着解压看到azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz这个文件名很多人的第一反应是“这个包是不是有点旧了”。SNAPSHOT 后缀确实意味着它不是一个稳妥的 release 版本但单机部署做实验、学调度、跑日常脚本这个包反而是最省事的入口。Azkaban 被很多团队用来替代手工 crontab核心原因是它给了你依赖管理、失败重试、日志回溯和 Web 界面而 solo-server 模式把这些能力打包进了一个进程里不依赖外部数据库也不用单独部署执行器。适合的场景很具体个人开发机、小团队内部服务、临时搭建的测试环境以及想搞懂调度系统原理的初学者。这篇文章要解决的就是一件事拿到这个 tar.gz 之后怎么在半小时内把它跑起来、跑稳并且知道哪些参数不能乱动。2. 部署前必须搞懂的 3 件事否则后面全是坑2.1 solo-server 和 two-server 模式的本质差异Azkaban 常见的部署形态有三种solo-server、two-server、multi-executor。这个包是 solo 模式意味着 Web 服务、调度器、执行器全部在一个 JVM 里启动。你可以把它理解成“带 Web 界面的单机任务调度进程”数据默认存在本地 H2 数据库里任务日志落本地磁盘不需要额外装 MySQL、Redis 这些依赖。two-server 模式则把 Web 端和执行器拆开执行器可以横向扩展。multi-executor 更激进多个执行器节点同时跑任务。这两种模式适合任务量大、需要高可用的生产环境但部署复杂度直线上升。对于绝大多数实验和内部工具场景solo 模式足够用。你拿到的这个包叫0.1.0-SNAPSHOT真正用的时候要注意Azkaban 官方 release 版本号一般是 3.x 系列。如果你是在某公司的内部镜像站或某个二次开发项目里拿到的这个包那它大概率是基于某个稳定版本加了定制化代码后重新打包的。这类包不一定有官方文档支撑部署时就更要依赖对配置文件的熟悉程度。2.2 JDK 版本是第一道门槛Azkaban 是 Java 生态的项目对 JDK 版本有硬性要求。solo-server 内置的启动脚本会去读JAVA_HOME环境变量如果找不到会直接报错退出。这个包年代比较久的话用的还是 JDK 8你把 JDK 17 放在JAVA_HOME里大概率启动到一半就报UnsupportedClassVersionError原因是编译时的 class 文件版本和运行时 JDK 不兼容。我一般会在部署前先确认两件事。第一机器上装了什么版本的 JDK执行java -version看输出。第二启动脚本里有没有硬编码的 Java 路径有的话直接改脚本比改环境变量更省心。另外solo 模式默认给 JVM 分配的内存不大我记得启动参数里通常是-Xmx2G左右如果你的任务需要更多内存后面讲配置时会提到在哪里改。# 确认当前 JDK 版本 java -version # 确认 JAVA_HOME 是否已设置 echo $JAVA_HOME # 如果 JAVA_HOME 为空临时指定以实际安装路径为准 export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64这段命令的作用是给启动脚本打好底子。第一条java -version看的是当前 shell 能直接用哪个 Java第二条看的是环境变量第三条是临时指定。Azkaban 的启动脚本bin/azkaban-solo-start.sh会优先使用JAVA_HOME下的 java 可执行文件所以第三条命令几乎是必执行的。注意export只对当前终端会话生效重启终端后要重新设置最稳妥的做法是写进~/.bashrc或~/.zshrc。2.3 解压后的目录结构每一层都要看懂解压这个 tar.gz 之后目录里通常会包含bin、conf、lib、extlib、plugins、logs和web这几个关键目录。很多人上来就执行启动脚本报错了才想起来看目录这不对。至少要知道conf里有全局配置文件bin里有启停脚本logs是排查问题的第一落点。extlib这个目录值得单独说。Azkaban 支持把额外依赖的 jar 包丢进去比如你要让任务能连上公司内部的某个消息队列就把对应的 client jar 放到这里重启后生效。plugins目录则存放各种 job 插件像jobtypes子目录里定义了每种 job 类型的默认配置。搞清楚这几个目录后面遇到“执行器找不到类”这类报错时你才知道往哪里补救。tar -zxvf azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz cd azkaban-solo-server-0.1.0-SNAPSHOT ls -la解压命令没什么玄学-z表示用 gzip 解压-x表示解包-v是显示过程-f指定文件名。解压后先ls -la看一眼目录结构重点确认bin/下有没有azkaban-solo-start.sh这个脚本。如果连启动脚本都不存在那这个包大概率打包不完整直接回头找运维或打包人确认别浪费时间硬调。3. 修改配置文件azkaban.properties 里的 5 个核心参数决定了任务调度成败3.1 配置文件在哪儿改改了哪些立即生效solo-server的全局配置在conf/azkaban.properties。这个文件是全项目的命门Web 端口、数据库连接、执行器线程数、时区设置全在这里。文件内容不多每行一个keyvalue注释行以#开头。初次部署没必要全看懂但有几个参数必须清楚是干什么的。3.2 端口配置冲突是最常见的启动失败原因# Web 服务监听端口 jetty.port8081 # 执行器服务端口 executor.port12321solo-server模式同时起了 Web 服务和执行器服务。jetty.port是你在浏览器里访问的端口默认 8081executor.port是执行器内部通信用端口默认 12321。这两个端口一旦被别的进程占用启动必然报Address already in use。我处理过好几次这类问题原因五花八门有人在本机跑着另一个 Tomcat 占了 8081有人开了多个 Azkaban 实例导致 12321 冲突。改端口没什么技巧改成没被占用的就行。怎么确认端口有没有被占用Linux 下用netstat -nltp | grep 8081macOS 下用lsof -i :8081看到 LISTEN 状态就说明被占了。这里给个建议测试环境用默认端口没问题但如果你打算让它长期跑着最好把端口改成不常用的高位端口降低冲突概率。# 检查端口占用情况 netstat -nltp | grep -E 8081|123213.3 数据库配置H2 文件位置决定了你的任务历史能不能保留# 默认使用 H2 数据库文件存放在本地 database.typeh2 h2.path./dbsolo-server 默认用 H2 数据库数据文件存在./db目录下。这里有个容易被忽略的点h2.path是相对路径相对于启动脚本的执行目录。你如果在/opt/azkaban目录下执行启动命令数据库文件就在/opt/azkaban/db如果在其他目录执行就会在那个目录下新建一个 db 目录。这会导致一个问题你在两个不同目录下分别启动过这个服务会得到两套完全独立的任务记录。所以第一次启动前就把工作目录固定好以后每次都在同一个目录下启停服务。H2 文件数据库的好处是零依赖缺点也很明显任务执行记录、调度历史、项目包都存这个文件里文件一旦损坏或丢失所有元数据全部完蛋。所以我习惯在测试完配置、跑通第一个任务之后把整个 db 目录手动备份一份成本极低后悔药还是要备着。3.4 时区设置调度时间对不上是最隐蔽的坑# 设置时区避免调度时间偏差 azkaban.tzAsia/Shanghai default.timezone.idAsia/Shanghai时区问题是我见过最隐蔽的坑。Azkaban 内部存储调度时间用的是 UTC前端展示时会根据配置的时区做转换。如果你不设置azkaban.tz和default.timezone.id默认是 UTC那么你在 Web 界面上定每天早上 8 点执行的任务实际触发时间是北京时间下午 4 点。很多人排查半天看日志、看数据库记录就是没往时区上想。这两行配置我一般都会加上明确设成所在的时区。改了之后要重启服务才生效。另外如果你把数据库从 H2 换成了 MySQL时区问题会更复杂因为 MySQL 连接串里的serverTimezone参数也要一起对齐。3.5 执行器参数并发度和内存决定任务跑得快不快# 执行器允许的最大并发任务数 executor.maxThreads50 # 任务默认运行目录 executor.port12321executor.maxThreads控制的是执行器同时能跑多少个任务默认值是 50。这个数字不是越大越好solo-server 是单机模式所有任务共用一个 JVM线程数设置太高CPU 上下文切换开销会拖慢每个任务设置太低任务排队严重。个人经验单机 4 核 8G 的机器10 到 20 之间比较合适。这个参数改完要重启执行器才生效。另外还有几个内存相关参数不在 properties 里而在启动脚本bin/azkaban-solo-start.sh顶部通常是JAVA_OPTS或AZKABAN_OPTS变量。需要加大堆内存就改这里。修改后重启生效。下面的参数速查表存一下部署时对照着查就够了。参数名作用默认值建议jetty.portWeb 界面访问端口8081被占用时改高位端口executor.port执行器内部通信端口12321被占用时改高位端口database.type数据库类型h2生产环境可换 mysqlh2.pathH2 数据文件路径./db固定启动目录再启动azkaban.tz调度时区空(UTC)必须显式设置executor.maxThreads最大并发任务数50小机器调到 10~204. 启动 solo-server并跑通第一个 Flow4.1 首次启动的命令与日志观察点配置改完之后执行启动脚本。启动过程大概 10 到 30 秒取决于机器性能。启动成功的标志是日志里出现Server started或者Jetty Server started之类的关键字。bin/azkaban-solo-start.sh启动 shell 脚本注意不要CtrlC杀掉。这个脚本默认在前台运行日志输出会直接打到终端上。如果你关掉终端进程就没了。想要后台运行建议用 nohup 或写个 systemd service 管理。日志会同时写到logs/azkaban-webserver.log排查问题时优先看这个文件。启动完成之后浏览器访问http://localhost:8081默认登录账号密码都是azkaban。登录进去之后你会看到项目列表页这时候还是空的因为还没有创建任何项目。4.2 创建一个最简单的 Flow从文件到执行Azkaban 里调度的基本单位是 Project一个 Project 包含一个或多个 Flow一个 Flow 包含多个 Job。Job 是真正的执行单元可以跑 shell 命令、Java 程序、Python 脚本等。这里我们先创建一个最简单的 Flow一个打印 Hello 的 Shell 任务。先在本地建一个项目目录里面放两个文件.project和basic.flow。# .project 文件声明项目基本信息 azkaban-flow-version: 2.0.project文件声明了这个项目使用的是 Azkaban Flow 的 2.0 版本语法。Azkaban 有 1.0 和 2.0 两套语法2.0 用的是 YAML可读性好很多新项目建议直接用 2.0。如果这个文件缺失或版本写错上传 zip 包时会被拒绝。接着写 flow 文件# basic.flowYAML 语法定义一个包含单个 job 的 flow config: # 定义 flow 级别的参数job 里可以用 ${param1} 引用 param1: hello_from_azkaban nodes: - name: jobA type: command config: command: echo ${param1}这个 flow 文件定义了一个节点jobA类型是command执行命令是echo hello_from_azkaban。config里的param1是自定义参数通过${param1}引用。Azkaban 在运行时会把参数展开成实际值。 parameters 化的好处是同一个 flow 可以复用只要在上传时或执行前覆盖参数值就能跑出不同结果。把这两个文件放到一个目录下打成 zip 包。注意 zip 包的根目录必须直接包含这两个文件不能有多余的外层文件夹。mkdir /tmp/azkaban-demo cd /tmp/azkaban-demo # 写入 .project 和 basic.flow 文件 zip -r basic.zip .project basic.flow打包这一步最容易犯的错误是打成demo/basic.zip这种结构。Azkaban 解压项目包时只看 zip 根目录下的文件如果找不到.project上传会直接失败。另外 zip 包不要加密不要用 mac 默认的__MACOSX隐藏目录这些都会干扰解析。4.3 上传项目并执行 Flow验证调度链路在 Web 界面上点击「Create Project」输入项目名和描述。创建完成后进入项目详情页点「Upload」按钮上传basic.zip。上传成功后界面上会出现basic这个 Flow。点击 Flow 旁边的Execute Flow按钮会弹出执行参数页面。这里有个非常重要的选项Schedule还是Execute。Execute是立即执行一次Schedule是设定周期性调度。首次验证建议先点Execute跑通了再谈调度。执行后点击执行记录里的 Job 名称能看到标准输出、错误日志、启动时间等。看到hello_from_azkaban的输出说明整个链路已经通了项目上传、Flow 解析、Job 执行、日志回传全部正常。到这里整个 solo-server 部署链路已经完整走通。从解压 tar.gz 到跑通第一个 Flow熟练之后全程不会超过 20 分钟。5. 部署避坑手册solo-server 最常见的 5 个故障与排查方法5.1 提示JVM 启动失败或秒退现象执行启动脚本后进程几秒钟就消失logs/azkaban-webserver.log里出现UnsupportedClassVersionError或Could not reserve enough space for object heap。原因JAVA_HOME指向的 JDK 版本过高class 文件版本不兼容或者启动脚本里Xmx设置的值超过了机器可用内存。解决把JAVA_HOME指向 JDK 8推荐用java-8-openjdk系列。如果是内存不足把启动脚本里的-Xmx调到机器物理内存的一半以下。改完source一下环境变量再重启。5.2 提示8001 端口被占用Web 打不开现象浏览器访问http://localhost:8081一直转圈或直接拒绝连接日志报java.net.BindException: Address already in use。原因8081 端口被其他服务占用最常见的是之前启动过 Tomcat或者另一个 Azkaban 实例没完全停止。解决执行netstat -nltp | grep 8081找出占用进程处理掉之后重试。如果这个端口实在腾不出来就改jetty.port到 8082 或 9090。改完别忘记重启。5.3 提示上传 zip 包时提示 Project file not found现象点击 Upload 后界面报azkaban.project.ProjectManagerException: Project file not found。原因zip 包根目录下没有.project文件或者 zip 包外层多套了一层文件夹。解决重新打包确保.project和 flow 文件在 zip 的根目录下。用unzip -l basic.zip命令查看 zip 内部结构看到第一层就是.project和basic.flow才对了。另外.project文件内容里的azkaban-flow-version那个值最好显式写2.0版本缺失也可能报这个错。5.4 提示Flow 执行后一直处于 Preparing 或 Running 状态现象任务执行后状态长时间停在Preparing或者卡在Running超过预期时间日志没有任何输出。原因solo-server 模式下Web 服务和执行器是同一个进程但任务调度和任务执行是独立的模块。executor.port如果被防火墙策略挡了或者本机/etc/hosts把主机名解析到了 127.0.0.1 之外执行器内部通信就会失败任务永远无法真正投递。解决首先确认executor.port没被占用其次检查执行器日志logs/azkaban-executor.log里有没有通信异常。如果是在云服务器上部署安全组里要把这个端口放通。本机测试时最常见的原因反而是主机名解析问题把/etc/hosts里主机名对应到 127.0.0.1 能解决大部分case。5.5 提示调度时间一直对不上定时任务不按预期触发现象在 Schedule 里设了每天早上 8 点执行结果 4 点就跑了或者到点了没跑。原因时区配置缺失或配置错误。Azaban 存储时间用的是 UTC如果你机器时区是北京时区而azkaban.properties里没配置azkaban.tzAsia/Shanghai界面显示的时间会和实际触发时间相差 8 小时。解决在azkaban.properties里同时加上azkaban.tzAsia/Shanghai和default.timezone.idAsia/Shanghai重启服务。改完之后去 Schedule 页面看一眼时间转换是否正常。6. 让 solo-server 跑得更顺手的 4 个进阶习惯到这步基础部署和避坑你已经顺手了。solo-server 虽然定位是单机但只要养成了几个好习惯它也能把小团队里的大部分定时任务管得井井有条。第一个习惯用命令行 API 提交任务而不是每次打开浏览器。Azkaban 提供了一组 HTTP API用 curl 就能完成创建项目、上传 zip、执行 flow、查询状态这套操作。我把常用的几条 curl 命令存成了一个脚本新机器上部署完直接跑脚本就能自动验证环境是否就绪。用 API 的额外好处是后续如果要把调度接入公司的内部平台这些命令就是现成的对接格式。# 先登录获取 session id curl -k -X POST --data actionloginusernameazkabanpasswordazkaban \ http://localhost:8081 # 用返回的 session.id 上传项目包执行 flow curl -k -X POST --data session.idxxxajaxexecuteprojecttestflowbasic \ http://localhost:8081/executor这段命令里的session.id是登录接口返回的字段每次会话有效。上传和执行的接口路径是固定的官方 API 文档里都有。用 API 做自动化部署验证比自己手动点界面快得多。第二个习惯把常用的 flow 参数抽出来放到项目级别的config里而不是散落在各个 job 里。比如数据库连接串、文件路径、环境标识这些每个 job 都可能用到的东西统一在 flow 顶层定义job 里用${variable}引用。这样要改环境时只改一处重传包就完事。这个习惯对上生产环境帮助尤其大。第三个习惯磁盘清理要制度化。solo-server 跑久了logs目录和项目执行日志会越来越大。尤其是执行日志每个 job 都会有独立文件跑得频繁的话一个月能吃掉几个 G。我一般会在服务器上挂一个 crontab每周清理超过 30 天的日志。Azkaban 有日志保留策略配置但手动 crontab 更直接可控。第四个习惯单独备份 H2 数据库目录。前面说过h2.path./db存了全部元数据。我吃过一次亏机器重启后 H2 文件损坏整个项目列表和调度记录全部丢失。后来每次跑完重要任务变更我就把 db 目录打个 tar 包放到另一块磁盘。恢复时直接解压覆盖服务重启就能回来。这个操作的成本基本为零但真出事的时候是救命的。solo-server 模式不是生产环境的最佳选择但它是理解 Azkaban 内部工作机制的最好起点。等你在这台单机实例上跑了几十个流程搞清楚 Flow、Job、参数传递、日志回溯这些概念之后再往 two-server 模式迁移就会顺畅得多。我就是这样一步步走过来的踩过的坑整理成这篇手册希望帮到你。本文还有配套的精品资源点击获取