1 案例
1.1 Hello World
first.project
azkaban-flow-version: 2.0
first.flow
nodes:
- name: jobA
type: command
config:
command: echo "hi 大佬"
打包为zip,即可上传
name:job名称
type:job类型。command表示要执行作业的方式为命令。
config:job配置
1.2 作业依赖案例
需求:JobA和Job执行完了,才能执行 JobC
pojo.project
azkaban-flow-version: 2.0
pojo.flow
nodes:
- name: jobC
type: command
dependsOn:
- jobA
- jobB
config:
command: echo "hi 大佬"
- name: jobA
type: command
config:
command: echo "开始执行 jobA"
- name: jobB
type: command
config:
command: echo "开始执行 jobB"
dependsOn: 作业依赖

1.3 自动失败重试
需求:如果执行任务失败,需要重试3次,重试时间间隔10000ms
pojo.flow
nodes:
- name: jobA
type: command
config:
command: sh /usr/local/azkaban/test/test.sh
retries: 3
retry.backoff: 10000
retries
: 重试次数
retry.backoff
: 重试的时间间隔
1.4 手动失败重试
需求:JobA->jobF,一次依赖吗,在生产环境,任何job都有可能挂掉,可以根据需求执行想要执行的job。
pojo.flow
nodes:
- name: jobA
type: command
config:
command: echo "执行jobA"
- name: jobB
type: command
dependsOn:
- jobA
config:
command: echo "执行jobB"
- name: jobC
type: command
dependsOn:
- jobB
config:
command: echo "执行jobC"
- name: jobD
type: command
dependsOn:
- jobC
config:
command: echo "执行jobD"
- name: jobE
type: command
dependsOn:
- jobD
config:
command: echo "执行jobE"
- name: jobF
type: command
dependsOn:
- jobE
config:
command: echo "执行jobF"


或者禁止

2 JavaProcess作业案例
JavaProcess类型可以运行一个自定义主类方法,type类型为javaprocess,可用配置为:
Xms: 最小堆
Xmx: 最大堆
classpath: 类路径
java.class: 要运行的java对象,必须包含Main方法
main.args: main方法的参数
案例:
1、新建一个azkaban的maven工程: azkaban_cs
2、创建包名:com.cs
3、创建 AzTest类
package com.cs;
public class AzTest {
public static void main(String[] args) {
System.out.println("java测试AzTest");
}
}
4、然后打包: azkaban_cs-1.0-SNAPSHOT.jar
5、testJava.flow
nodes:
- name: test_java
type: javaprocess
config:
Xms: 96M
Xmx: 200M
java.class: com.cs.AzTest
3 条件工作流
条件工作流功能允许用户自定义执行条件来决定是否运行某些job。条件可以由当前job的父job输出运行时的参数构成,也可以使用预定义宏。在这些条件下,用户可以在确定job执行逻辑时获得更大的灵活性,例如,至于只要父job之一成功,就可以运行当前job。
3.1 运行时参数
1、运行原理
- 父job将参数写入 JOB_OUTPUT_PROP_FILE 环境变量所指向的文件。
- 子job使用 ${jobName:param} 来获取父job输出的参数并定义执行条件。
2、支持的运算符
==、!=、>、<、>=、<=、&& 与、
3、需求案例
- jobA执行一个shell脚本
- jobB执行一个shell脚本,但jobB不需要每天都执行,而只需要每周一执行。

jobA.sh
#!/bin/bash
echo "执行jobA"
wk=`date +%w`
echo "{\"wk\":$wk}" > $JOB_OUTPUT_PROP_FILE
jobB.sh
#!/bin/bash
echo "执行jobB"
condition.flow
nodes:
- name: jobA
type: command
config:
command: sh JobA.sh
- name: jobB
type: command
dependsOn:
- jobA
config:
command: sh jobB.sh
condition: ${jobA:wk} == 1
3.2 预定义宏案例
Azkaban中预置了几个特殊的判断条件,称为预定义宏。
预定义宏会根据所有父job的完成情况进行判断,在决定是否执行。可用的预定义宏入下:
1、all_sucess: 表示父job全部成功才执行(默认)
2、all_done:表示父job全部完成才执行
3、all_failed:表示父job全部失败才执行
4、one_sucess:表示父job至少一个成功才执行
5、one_failed:表示父job至少一个失败才执行
需求:
- jobA执行一个shell脚本
- jobB执行一个shell脚本
- jobC执行一个shell脚本,要求jobA、jobB中有一个成功即可执行。

jobA.sh
#!/bin/bash
echo "执行jobA"
jobB.sh
#!/bin/bash
echo "执行jobB"
jobC.sh
#!/bin/bash
echo "执行jobC"
marco.flow
nodes:
- name: jobA
type: command
config:
command: sh jobA.sh
- name: jobB
type: command
config:
command: sh jobB.sh
- name: jobC
type: command
dependsOn:
- jobA
- jobB
config:
command: sh jobC.sh
condition: one_success
4 定时执行


需求:jobA 每隔1分钟执行一次
使用方法同 cron,具体参考:https://www.couragesteak.com/article/189
5 报警
5.1 邮件
修改配置文件
cd /usr/local/azkaban/azkaban-web-server-3.84.4
vim conf/azkaban.properties
mail.sender=发件人邮箱
mail.host=SMTP服务器地址
mail.user=
mail.password=
重启 web server
cd /usr/local/azkaban/azkaban-web-server-3.84.4
bin/shutdown-web.sh
bin/start-web.sh

5.2 电话告警
通常邮件报警可能会不及时,因此需要电话来及时通知。可与第三方平台进行集成。
睿象云:https://www.aiops.com/
5 Azkaban 多 Executor 模式注意事项
Azkaban 多 Executor模式指:在集群中多个节点部署 Executor。在这种模式下, Azkaban web server会根据策略,选取其中一个 Executor 去执行任务。
为确保所选的 Executor 能够准确的执行任务,我们须在一下两种方案任选其一,推荐方案二。
方案一:在特定的 Executor 去执行任务
1、在 MySQL 中 azkaban 数据库 executors 表中,查询 Executor的id。
use azkaban;
select * from executors;

这是任务脚本,可以写为绝对路径。
方案二:在 Executor 所在所有节点部署任务所需的脚本和应用。
[1] https://www.bilibili.com/video/BV1y54y18713 感谢尚硅谷
<h2><a id="1__0"></a>1 案例</h2>
<h3><a id="11_Hello_World_2"></a>1.1 Hello World</h3>
<p>first.project</p>
<pre><div class="hljs"><code class="lang-shell">azkaban-flow-version: 2.0
</code></div></pre>
<p>first.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"hi 大佬"</span>
</code></div></pre>
<p>打包为zip,即可上传</p>
<p>name:job名称</p>
<p>type:job类型。command表示要执行作业的方式为命令。</p>
<p>config:job配置</p>
<h3><a id="12__32"></a>1.2 作业依赖案例</h3>
<p>需求:JobA和Job执行完了,才能执行 JobC</p>
<p>pojo.project</p>
<pre><div class="hljs"><code class="lang-shell">azkaban-flow-version: 2.0
</code></div></pre>
<p>pojo.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobC</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-comment"># JobC 依赖于 JobA 和 JobB</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobA</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"hi 大佬"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"开始执行 jobA"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"开始执行 jobB"</span>
</code></div></pre>
<p>dependsOn: 作业依赖</p>
<p><img src="https://static.couragesteak.com/article/f49e1a3ef189489bb9cb49d8d2de7584.png" alt="image.png" /></p>
<h3><a id="13__70"></a>1.3 自动失败重试</h3>
<p>需求:如果执行任务失败,需要重试3次,重试时间间隔10000ms</p>
<p>pojo.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">/usr/local/azkaban/test/test.sh</span>
<span class="hljs-attr">retries:</span> <span class="hljs-number">3</span>
<span class="hljs-attr">retry.backoff:</span> <span class="hljs-number">10000</span>
</code></div></pre>
<p><code>retries</code>: 重试次数</p>
<p><code>retry.backoff</code>: 重试的时间间隔</p>
<h3><a id="14__92"></a>1.4 手动失败重试</h3>
<p>需求:JobA->jobF,一次依赖吗,在生产环境,任何job都有可能挂掉,可以根据需求执行想要执行的job。</p>
<p>pojo.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobA"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobB"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobC</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobC"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobD</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobC</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobD"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobE</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobD</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobE"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobF</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobE</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"执行jobF"</span>
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/b25839eaf378117d991b14f81fa60ac2.png" alt="image20221222141909262.png" /></p>
<p><img src="https://static.couragesteak.com/article/3fced41309cae2b7067d6caeb3c09761.png" alt="image20221222142301936.png" /></p>
<p>或者禁止</p>
<p><img src="https://static.couragesteak.com/article/50fcdcd343309ec333beea06bd7bf75e.png" alt="image20221222142450190.png" /></p>
<h2><a id="2_JavaProcess_151"></a>2 JavaProcess作业案例</h2>
<p>JavaProcess类型可以运行一个自定义主类方法,type类型为javaprocess,可用配置为:</p>
<pre><code class="lang-">Xms: 最小堆
Xmx: 最大堆
classpath: 类路径
java.class: 要运行的java对象,必须包含Main方法
main.args: main方法的参数
</code></pre>
<p>案例:</p>
<p>1、新建一个azkaban的maven工程: azkaban_cs</p>
<p>2、创建包名:com.cs</p>
<p>3、创建 AzTest类</p>
<pre><div class="hljs"><code class="lang-java"><span class="hljs-keyword">package</span> com.cs;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AzTest</span> {
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> {
System.out.println(<span class="hljs-string">"java测试AzTest"</span>);
}
}
</code></div></pre>
<p>4、然后打包: azkaban_cs-1.0-SNAPSHOT.jar</p>
<p>5、testJava.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">test_java</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">javaprocess</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">Xms:</span> <span class="hljs-string">96M</span>
<span class="hljs-attr">Xmx:</span> <span class="hljs-string">200M</span>
<span class="hljs-attr">java.class:</span> <span class="hljs-string">com.cs.AzTest</span>
</code></div></pre>
<h2><a id="3__197"></a>3 条件工作流</h2>
<p>条件工作流功能允许用户自定义执行条件来决定是否运行某些job。条件可以由当前job的父job输出运行时的参数构成,也可以使用预定义宏。在这些条件下,用户可以在确定job执行逻辑时获得更大的灵活性,例如,至于只要父job之一成功,就可以运行当前job。</p>
<h3><a id="31__201"></a>3.1 运行时参数</h3>
<p>1、运行原理</p>
<ul>
<li>父job将参数写入 JOB_OUTPUT_PROP_FILE 环境变量所指向的文件。</li>
<li>子job使用 ${jobName:param} 来获取父job输出的参数并定义执行条件。</li>
</ul>
<p>2、支持的运算符</p>
<p>==、!=、>、<、>=、<=、&& 与、</p>
<p>3、需求案例</p>
<ul>
<li>jobA执行一个shell脚本</li>
<li>jobB执行一个shell脚本,但jobB不需要每天都执行,而只需要每周一执行。</li>
</ul>
<p><img src="https://static.couragesteak.com/article/0704f54515fc4fd23dc30580aeab71de.png" alt="image20221222163321137.png" /></p>
<p>jobA.sh</p>
<pre><div class="hljs"><code class="lang-sh"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"执行jobA"</span>
wk=`<span class="hljs-built_in">date</span> +%w`
<span class="hljs-built_in">echo</span> <span class="hljs-string">"{\"wk\":<span class="hljs-variable">$wk</span>}"</span> > <span class="hljs-variable">$JOB_OUTPUT_PROP_FILE</span>
</code></div></pre>
<p>jobB.sh</p>
<pre><div class="hljs"><code class="lang-sh"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"执行jobB"</span>
</code></div></pre>
<p>condition.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">JobA.sh</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">jobB.sh</span>
<span class="hljs-attr">condition:</span> <span class="hljs-string">${jobA:wk}</span> <span class="hljs-string">==</span> <span class="hljs-number">1</span>
</code></div></pre>
<h3><a id="32__257"></a>3.2 预定义宏案例</h3>
<p>Azkaban中预置了几个特殊的判断条件,称为预定义宏。</p>
<p>预定义宏会根据所有父job的完成情况进行判断,在决定是否执行。可用的预定义宏入下:</p>
<p>1、all_sucess: 表示父job全部成功才执行(默认)</p>
<p>2、all_done:表示父job全部完成才执行</p>
<p>3、all_failed:表示父job全部失败才执行</p>
<p>4、one_sucess:表示父job至少一个成功才执行</p>
<p>5、one_failed:表示父job至少一个失败才执行</p>
<p>需求:</p>
<ul>
<li>jobA执行一个shell脚本</li>
<li>jobB执行一个shell脚本</li>
<li>jobC执行一个shell脚本,要求jobA、jobB中有一个成功即可执行。</li>
</ul>
<p><img src="https://static.couragesteak.com/article/7c4994a4b217052b4130db9d42e5d8b4.png" alt="image20221222163958102.png" /></p>
<p>jobA.sh</p>
<pre><div class="hljs"><code class="lang-sh"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"执行jobA"</span>
</code></div></pre>
<p>jobB.sh</p>
<pre><div class="hljs"><code class="lang-sh"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"执行jobB"</span>
</code></div></pre>
<p>jobC.sh</p>
<pre><div class="hljs"><code class="lang-sh"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"执行jobC"</span>
</code></div></pre>
<p>marco.flow</p>
<pre><div class="hljs"><code class="lang-yaml"><span class="hljs-attr">nodes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobA</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">jobA.sh</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">jobB.sh</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">jobC</span>
<span class="hljs-attr">type:</span> <span class="hljs-string">command</span>
<span class="hljs-attr">dependsOn:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobA</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">jobB</span>
<span class="hljs-attr">config:</span>
<span class="hljs-attr">command:</span> <span class="hljs-string">sh</span> <span class="hljs-string">jobC.sh</span>
<span class="hljs-attr">condition:</span> <span class="hljs-string">one_success</span>
</code></div></pre>
<h2><a id="4__330"></a>4 定时执行</h2>
<p><img src="https://static.couragesteak.com/article/afae20409a6260e8990344b9968162e3.png" alt="image20221222165119880.png" /></p>
<p><img src="https://static.couragesteak.com/article/57ad7931c4759111a138f80e8c644438.png" alt="image20221222165357235.png" /></p>
<p>需求:jobA 每隔1分钟执行一次</p>
<p>使用方法同 cron,具体参考:<a href="https://www.couragesteak.com/article/189" target="_blank">https://www.couragesteak.com/article/189</a></p>
<h2><a id="5__341"></a>5 报警</h2>
<h3><a id="51__343"></a>5.1 邮件</h3>
<p>修改配置文件</p>
<pre><div class="hljs"><code class="lang-shell">cd /usr/local/azkaban/azkaban-web-server-3.84.4
vim conf/azkaban.properties
</code></div></pre>
<pre><div class="hljs"><code class="lang-shell">mail.sender=发件人邮箱
mail.host=SMTP服务器地址
mail.user=
mail.password=
</code></div></pre>
<p>重启 web server</p>
<pre><div class="hljs"><code class="lang-shell">cd /usr/local/azkaban/azkaban-web-server-3.84.4
bin/shutdown-web.sh
bin/start-web.sh
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/2496bc8252e66df3020f5fedc620e2ca.png" alt="image.png" /></p>
<h3><a id="52__366"></a>5.2 电话告警</h3>
<p>通常邮件报警可能会不及时,因此需要电话来及时通知。可与第三方平台进行集成。</p>
<p>睿象云:https://www.aiops.com/</p>
<h2><a id="5_Azkaban__Executor__373"></a>5 Azkaban 多 Executor 模式注意事项</h2>
<p>Azkaban 多 Executor模式指:在集群中多个节点部署 Executor。在这种模式下, Azkaban web server会根据策略,选取其中一个 Executor 去执行任务。</p>
<p>为确保所选的 Executor 能够准确的执行任务,我们须在一下两种方案任选其一,推荐方案二。</p>
<p>方案一:在特定的 Executor 去执行任务</p>
<p>1、在 MySQL 中 azkaban 数据库 executors 表中,查询 Executor的id。</p>
<pre><div class="hljs"><code class="lang-shell">use azkaban;
select * from executors;
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/e2a633cd8ba472dfeebb9c73810c4e53.png" alt="image.png" /></p>
<p>这是任务脚本,可以写为绝对路径。</p>
<p>方案二:在 Executor 所在所有节点部署任务所需的脚本和应用。</p>
<p>[1] https://www.bilibili.com/video/BV1y54y18713 感谢尚硅谷</p>
留言