Azkaban知识点总结

一、Azkaban概述

1.1 Azkaban简介

Azkaban是由Linkedin公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺序运行一组工作和流程;它的配置是通过简单的key:value对的方式,通过配置中的Dependencies来设置依赖关系。Azkaban使用job配置文件建立任务之间的依赖关系,并提供一个易于使用web用户界面维护和跟踪你的工作流。

1.2 为什么需要工作流调度系统

  1. 一个完整的数据分析系统通常都是由大量任务单元组成;

    Shell脚本程序,Java程序,MapReduce程序,Hive脚本等

  2. 各任务单元之间存在时间先后或前后依赖关系;

  3. 为了更好的组织起这样的复杂执行计划,需要一个工作流调度系统来调度执行。

在这里插入图片描述

1.3 常见的工作流调度系统

  1. 简单的任务调度

    直接使用crontab实现

  2. 复杂的任务调度

    开发调度平台或使用现成的开源调度系统(如Ooize,Azkaban等)

1.4 Azkaban特点

  1. 兼容任何版本的hadoop;
  2. 易于使用的web用户界面;
  3. 简单的工作流的上传;
  4. 方便设置任务之间的关系;
  5. 调度工作流;
  6. 认证/授权(权限的工作);
  7. 模块化和可插拔的插件机制;
  8. 能够杀死并重新启动工作流;
  9. 有关失败和成功的电子邮件提醒。

1.5 Azkaban的架构

Azkaban由三个关键组件构成:
在这里插入图片描述

  • Web Server:是整个Azkaban工作流系统的主要管理者;它用于用户登录、负责project管理、定时执行工作流、跟踪工作流执行进度等一系列任务;
  • Executor Server:负责具体的工作流的提交、执行,它们通过mysql数据库来协调任务的执行;
  • MySQL:存储大部分执行流状态,Web Server和Executor Server都需要访问数据库。

二、源码构建(azkaban-3.90.0.zip)

Gradle和maven是竞争对手,在home目录(root用户/root)有一个.gradle的目录(隐藏),相当于maven本地仓库。

  1. 安装zip和unzip命令

    yum -y install zip unzip

  2. 解压、重命名

  3. 构建javac,要把.java文件变成.class文件

    ./gradlew build

  4. 安装git

    yum -y install git

  5. 打包

    ./gradlew installDist

  6. 把class文件删除,重新编译

    ./gradlew clean

三、单机(azkaban-solo-server)

  1. 修改配置文件(start-solo.sh)

    添加环境变量:HDAOOP_HOME

  2. 启动服务器

    bin/start-solo.sh

  3. 访问网页

    node7-2:8081

  4. 用户名和密码配置文件

    conf/zakaban-users.xml

四、多机

4.1 配置前部署

  1. 时间统一修改为东八区

    修改配置文件azkaban-exec-server/conf/azkaban.properties

    default.timezone.id=Asia/Shanghai

  2. 数据库(创建azkaban数据库)

    添加配置文件my.ini到mysql本地安装目录,之后重启mysql

    [mysqld]
    log-bin-trust-function-creators=true
    max_allowed_packet=1024M
    
  3. 导入脚本

    azkaban-sou/azkaban-db/build/distributions/.tar或.zip都可以/create-all-sql-0.1.0-SNAPSHOT.sql

  4. 部署

    node7-1node7-2node7-3node7-4
    Web Server
    Executor Server

4.2 部署Executor Server

  1. 替换mysql最新驱动包

    mysql-connect-java-5.1.49.jar

  2. 修改配置文件(conf/azkaban.properties)

    # mysql相关信息
    azkaban.webserver.url=http://node7-2:8081
    
    database.type=mysql
    mysql.port=3306
    mysql.host=192.168.56.1
    mysql.database=azkaban
    mysql.user=root
    mysql.password=123456
    mysql.numconnections=100
    
  3. 修改配置文件(bin/start-exec.sh)

    添加环境变量:HADOOP_HOME

  4. 启动服务器

    bin/start-exec.sh

  5. 停止服务器

    bin/shutdown-exec.sh

  6. 激活executor每次重启一定要激活

    curl -G "/localhost:$(<./executor.port)/executor?action=activate" && echo

4.3 部署Web Server

  1. 修改配置文件(conf/azkaban.properties和bin/start-web.sh)

  2. 替换mysql最新驱动包

    mysql-connect-java-5.1.49.jar

  3. 启动服务器

    bin/start-web.sh

4.4 网页使用

  1. 创建两个文件

    flow20.project

    azkaban-flow-version:2.0
    

    basic.flow(不能用tab键)(相互依赖)

    nodes:
      -name:jobC
        type:noop
        # jobC depends on jobA and jobB
        dependsOn:
          -jobA
          -jobB
          
      -name:jobA
        type:command
        config:
          command:echo "This is an echoed text."
          
      -name:jobB
        type:command
        config:
          command:pwd
    
  2. 把这两个文件打一个zip包(不要使用中文命名)

五、JavaSE编程连接api

ApiUtil.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;

/**
 * azkaban的api工具类
 */
public class ApiUtil {
    private String serverUrl = "http://node7-2:8081/";

    /**
     * 登录
     * @param user  用户名
     * @param password  密码
     * @return  将服务器返回的字符串解析为JSON
     */
    public JSONObject login(String user, String password) {
        System.out.println("--ApiUtil--login--");
        String requestUrl = serverUrl;
        HttpUtil httpUtil = new HttpUtil();

        Map<String, String> headerMap = new HashMap<String, String>();
        // 加一个请求头
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");

        Map<String, String> requestMap = new HashMap<String, String>();
        requestMap.put("username", user);
        requestMap.put("password", password);
        requestMap.put("action", "login");

        Map<String, String> responseMap = new HashMap<String, String>();
        // 请求网页
        // String response = httpUtil.methodGet(requestUrl, headerMap, requestMap, responseMap);
        String response = httpUtil.methodPost(requestUrl,headerMap, requestMap, responseMap);

        System.out.println("--headerMap--" + headerMap);
        System.out.println("--requestMap--" + requestMap);
        System.out.println("--responseMap--" + responseMap);
        System.out.println("--返回结果--" + response);
        return (JSONObject) JSON.parse(response);
    }

    /**
     * 登录
     * @param sessionId 用户名
     * @param name  密码
     * @param description   描述
     * @return  将服务器返回的字符串解析为JSON
     */
    public JSONObject create(String sessionId, String name, String description) {
        System.out.println("--ApiUtil--create--");
        String requestUrl = serverUrl + "manager";
        HttpUtil httpUtil = new HttpUtil();

        Map<String, String> headerMap = new HashMap<String, String>();
        // 加一个请求头
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");

        Map<String, String> requestMap = new HashMap<String, String>();
        requestMap.put("name", name);
        requestMap.put("description", description);
        requestMap.put("action", "login");

        Map<String, String> responseMap = new HashMap<String, String>();
        // 请求网页
        String response = httpUtil.methodPost(requestUrl,headerMap, requestMap, responseMap);

        System.out.println("--headerMap--" + headerMap);
        System.out.println("--requestMap--" + requestMap);
        System.out.println("--responseMap--" + responseMap);
        System.out.println("--返回结果--" + response);
        return (JSONObject) JSON.parse(response);
    }
}

ClientMain.java

import com.alibaba.fastjson.JSONObject;

public class ClientMain {
    public static void main(String[] args) {
        ApiUtil apiUtil = new ApiUtil();
        String user = "azkaban";
        String password = "azkaban";
        JSONObject resultJSON = apiUtil.login(user, password);
        System.out.println("--返回--" + resultJSON.toJSONString());
        System.out.println("--响应码--" + resultJSON.get("session.id"));
        if ("success".equalsIgnoreCase(resultJSON.getString("status"))) {
            // 登录成功
            System.out.println("--登录成功--");
            String sessionId = resultJSON.get("session.id") + "";
            String name = "code_aaa";
            String describe = "code_bbb";
            resultJSON = apiUtil.create(sessionId, name, describe);
            System.out.println("--返回--" + resultJSON.toJSONString());
        }
    }
}

HttpUtil.java

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 封装整个http的网络请求
 * 它像一个浏览器
 */
public class HttpUtil {
    /**
     * get请求
     * @param requestUrl    请求的网址
     * @param headerMap     请求头
     * @param requestMap    请求体
     * @return  响应体
     */
    public String methodGet(String requestUrl, Map<String, String> headerMap, Map<String, String> requestMap, Map<String, String> responseMap) {
        System.out.println("--HttpUtil--methodGet--");

        try {
            /*
            信的内容的格式是:a=1&b=2&c=3&d=4
            =左边的叫键
            =右边的叫值
             */
            StringBuffer requestSb = new StringBuffer();
            for (Iterator iterator = requestMap.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                requestSb.append(key + "=" + value + "&");
            }
            System.out.println("--请求体--" + requestSb);
            if (requestUrl.indexOf("?") != -1) {
                requestUrl = requestUrl + "&" + requestSb.toString();
            } else {
                requestUrl = requestUrl + "?" + requestSb.toString();
            }
            System.out.println("--requestUrl--" + requestUrl);

            // 准备写信,收件人
            URL url = new URL(requestUrl);
            // 邮递员
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 写信封
            for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                connection.setRequestProperty(key, value);
            }
            // 默认是get请求
            connection.setRequestMethod("GET");

            // 写信的内容:得写到信封上
            StringBuffer sb = new StringBuffer();
            InputStream is = connection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            // 关闭BufferedReader
            br.close();

            // 设置回信的信封
            Map<String, List<String>> responseHeader = connection.getHeaderFields();
            // 写信封
            for (Iterator iterator = responseHeader.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                requestMap.put(key, value.toString());
            }
            return sb.toString();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * get请求
     * @param requestUrl    请求的网址
     * @param headerMap     请求头
     * @param requestMap    请求体
     * @param responseMap   响应头
     * @return  响应体
     */
    public String methodPost(String requestUrl, Map<String, String> headerMap, Map<String, String> requestMap, Map<String, String> responseMap) {
        System.out.println("--HttpUtil--methodPost--" + requestUrl);
        try {
            // 准备写信,收件人
            URL url = new URL(requestUrl);
            // 邮递员
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 写信封
            for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                connection.setRequestProperty(key, value);
            }
            // 默认是get请求
            connection.setRequestMethod("POST");
            // 输入,输出,都是允许
            connection.setDoInput(true);
            connection.setDoOutput(true);

            // 加一个信封的内容
            OutputStream os = connection.getOutputStream();
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
            StringBuffer requestSb = new StringBuffer();
            for (Iterator iterator = requestMap.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                requestSb.append(key + "=" + value + "&");
            }
            requestSb.delete(requestSb.lastIndexOf("&"), requestSb.length());
            System.out.println("--请求体--" + requestSb);

            // 写东西
            bw.write(requestSb.toString());
            bw.close();

            // 写信的内容:得写道信封上
            StringBuffer sb = new StringBuffer();
            InputStream is = connection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            // 关闭BufferedReader
            br.close();

            // 设置回信得信封
            Map<String, List<String>> responseHeader = connection.getHeaderFields();
            // 写信封
            for (Iterator iterator = responseHeader.entrySet().iterator();iterator.hasNext(); ) {
                Map.Entry me = (Map.Entry) iterator.next();
                String key = me.getKey() + "";
                String value = me.getValue() + "";
                // 设置信封的内容
                requestMap.put(key, value.toString());
            }
            return sb.toString();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void main(String[] args) {
        String requestUrl = "https://www.baidu.com";
        HttpUtil httpUtil = new HttpUtil();

        Map<String, String> headerMap = new HashMap<String, String>();
        Map<String, String> requestMap = new HashMap<String, String>();
        Map<String, String> responseMap = new HashMap<String, String>();

        // 请求网页
        String response = httpUtil.methodGet(requestUrl, headerMap, requestMap, responseMap);
        // String response = httpUtil.methodPost(requestUrl, headerMap, requestMap, responseMap);

        System.out.println("--headerMap--" + headerMap);
        System.out.println("--requestMap--" + requestMap);
        System.out.println("--responseMap--" + responseMap);
        System.out.println("--返回结果--" + response);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值