Azkaban Api

 项目地址

java azkaban api: https://github.com/poemp/springboot-azkaban

go azakaban api: https://github.com/poemp/go-azkaban-api

azkaban job:   https://github.com/poemp/azkaban-data-push-job

 

 项目原因   

       最近项目在做数据推送的时候,设计方式是采用分布式任务的方式推送到指定数据库中,所以采用azkaban,采用azkaban的原因有以下几点:

  • 查看日志

  日志查看方便。在之前做了一个系统,数据的引接和指标的计算,出现一个问题是,所有逻辑都在一个jar工程里面,遇到问题,需要查看日志的时候,所有日志都混合在一起,不是按照任务来区分,需要使用vim根据任务id去寻找需要的日志,比较麻烦。而使用azkaban,日志是根据任务分割开的,方便查看,并且,可以看到当前任务所执行时间。

查看日志方便

  • jar热更新

采用的是job的方式,不用每次修改调试都发一次版本,采用热更新。修改程序过后,重新打包job上传就可以执行,非常方便。

可以查看编写的job,地址是:https://github.com/poemp/azkaban-data-push-job,欢迎交流。

上传job

  • 编写的job不局限于Java

由于azkaban的job type多样性,所有编写job的语言不局限于Java,可以是Scala,Go, Python,Shell编写。

  • 和业务系统分离

不和业务系统在一起,方便部署管理。任务和业务系统在一起,特别麻烦的是定位问题,需要一大堆依赖,处理各种情况。

  • 调试方便

任务可以在azkaban里面方便的调试,而不需要真正的调用一次,只需要把使用的参数准备好,就可以执行一次job,非常方便

 

工程项目说明

azkaban工程项目地址:https://github.com/poemp/springboot-azkaban, 可以方便的继承在自己的工程项目里面,直接调用就可以。工程项目中使用到的是Http请求,组装参数,发送给azkaban做处理就好了,没有其他的技术点。

api说明

核心的代码说明

登录

主要是去拿通信的token


    /**
     * 登录
     */
    public void login() {
        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("action", "login");
        params.add("username", config.getUsername());
        params.add("password", config.getPassword());

        HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, getAzkabanHeaders());

        String respResult = restTemplate.postForObject(config.getUrl(), httpEntity, String.class);
        log.info("Result: " + respResult);
        try {
            JsonNode respRoot = objectMapper.readTree(respResult);
            if (respRoot.hasNonNull("status") && "success".equals(respRoot.get("status").asText())) {
                SESSION_ID = respRoot.get("session.id").asText();
                log.info("Azkaban login success:{}", respRoot);
            } else {
                log.warn("Azkaban login failure:{}", respRoot);
            }
        } catch (IOException e) {
            log.error(String.format("Azkaban login failure: %s !", e.getMessage()), e);
            throw new AzkabanException(e.getMessage());
        }
    }

创建项目

  /**
     * 创建项目
     *
     * @param projectName 项目名称
     * @param description 项目描述
     */
    public void createProject(String projectName, String description) {
        LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        parameters.add("session.id", SESSION_ID);
        parameters.add("action", "create");
        parameters.add("name", projectName);
        parameters.add("description", description);

        HttpEntity<LinkedMultiValueMap<String, String>> httpEntity = new HttpEntity<>(parameters, getAzkabanHeaders());

        String respResult = restTemplate.postForObject(config.getUrl() + "/manager", httpEntity, String.class);
        log.info("Result: " + respResult);
        try {
            JsonNode respRoot = objectMapper.readTree(respResult);
            if (respRoot.hasNonNull("status") && "success".equals(respRoot.get("status").asText())) {
                log.info("Azcaban create a Project: {}", projectName);
            } else {
                String errorMessage = respRoot.hasNonNull("message") ? respRoot.get("message").asText() : "No message.";
                log.error("Azcaban create Project %s failure: %s", projectName, errorMessage);
                throw new AzkabanException(errorMessage);
            }
        } catch (IOException e) {
            log.error(String.format("Azcaban create Project %s failure: %s", projectName, e.getMessage()), e);
            throw new AzkabanException(e.getMessage());
        }
    }

启动flow


    /**
     * 执行
     *
     * @param projectName 项目名称
     * @param flowId      flow
     * @param optionalParams 参数
     * @return
     */
    public String executeFLow(String projectName, String flowId, Map<String, Object> optionalParams) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8");
        Map<String, Object> map = new HashMap<>();
        if (optionalParams != null) {
            map.putAll(optionalParams);
        }
        map.put("session.id", SESSION_ID);
        map.put("ajax", "getRunning");
        map.put("project", projectName);
        map.put("flow", flowId);
        //flowOverride[type]=apple
        String paramStr = map.keySet().stream()
                .map(key -> "flowOverride["+ key + "]=" + map.get(key))
                .collect(Collectors.joining("&"));

        ResponseEntity<String> exchange = restTemplate.exchange(config.getUrl() + "/executor?" + paramStr, HttpMethod.GET,
                new HttpEntity<String>(httpHeaders), String.class);

        log.info("Azkban execute a Flow:{}", exchange);
        return exchange.toString();
    }

查询状态

  /**
     * 执行信息
     *
     * @param execId 执行ID
     * @return 结果
     */
    public String executionInfo(String execId) {
        LinkedMultiValueMap<String, Object> linkedMultiValueMap = new LinkedMultiValueMap<>();
        linkedMultiValueMap.add("session.id", SESSION_ID);
        linkedMultiValueMap.add("ajax", "fetchexecflow");
        linkedMultiValueMap.add("execid", execId);
        String res = restTemplate.postForObject(config.getUrl() + "/executor", linkedMultiValueMap, String.class);
        log.info("azkaban execution info:{}", res);
        return res;
    }

其中调用执行情况的代码片段是:

String s = azkabanAdapter.executionInfo(dataPushTaskHistory.getExecId());
            JSONObject result = JSONObject.parseObject(s);
            if ("SUCCEEDED".equals(result.getString("status"))) {
                dataPushTaskHistory.setStatus(3);
            } else if ("FAILED".equals(result.getString("status"))) {
                dataPushTaskHistory.setStatus(2);
            }

 

这样就完成了调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值