livy提交spark应用
spark-submit的使用shell时时灵活性较低,livy作为spark提交的一种工具,是使用接口或者java客户端的方式提交,可以集成到web应用中
1.客户端提交的方式
http://livy.incubator.apache.org/docs/latest/programmatic-api.html
核心代码
LivyClient client = new LivyClientBuilder()
.setURI(new URI(livyUrl))
.build(); try {
System.err.printf("Uploading %s to the Spark context...\n", piJar);
client.uploadJar(new File(piJar)).get(); System.err.printf("Running PiJob with %d samples...\n", samples);
double pi = client.submit(new PiJob(samples)).get(); System.out.println("Pi is roughly: " + pi);
} finally {
client.stop(true);
}
2.REST API
http://livy.incubator.apache.org/docs/latest/rest-api.html
1.以最常使用的batches接口作为例子,请求参数

rest 的http
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class HttpUtils {
//post 请求
public String postAccess(String url, Map<String, String> headers, String data) { HttpPost post = new HttpPost(url);
if (headers != null && headers.size() > 0) {
headers.forEach((K, V) -> post.addHeader(K, V));
}
try {
StringEntity entity = new StringEntity(data);
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
HttpEntity resultEntity = response.getEntity();
result = EntityUtils.toString(resultEntity);
return result;
} catch (Exception e) {
e.printStackTrace();
logger.error("postAccess执行有误" + e.getMessage());
}
return result;
}
}
livy提交spark应用类,异步线程进行状态打印或者也可以状态监控返回web端
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wanmi.sbc.dw.utils.GsonUtil;
import com.wanmi.sbc.dw.utils.HttpUtils;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component; import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List; /**
* @ClassName: com.spark.submit.impl.livy.LivyApp
* @Description: livy提交spark任务
* @Author: 小何
* @Time: 2020/12/15 10:46
* @Version: 1.0
*/
@Component
public class LivyServer {
private static final Logger logger = LoggerFactory.getLogger(LivyServer.class); private static final List<String> FAIl_STATUS_LIST = Arrays.asList("shutting_down", "error", "dead", "killed");
private final HashMap<String, String> headers; private HttpUtils httpUtils; public LivyServer() {
headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("X-Requested-By", "admin");
} /**
* 提交参数
*
* @param livyParam
* @return
*/
@SneakyThrows
public String batchSubmit(LivyParam livyParam) {
this.httpUtils = new HttpUtils();
String livyUri = livyParam.getLivyUri();
LivyParam livyParamCopy = new LivyParam();
BeanUtils.copyProperties(livyParam, livyParamCopy);
livyParamCopy.setLivyUri(null);
String request = GsonUtil.toJsonString(livyParamCopy);
logger.info("任务提交信息{}", request);
String result = httpUtils.postAccess(livyUri + "/batches", headers, request);
if (!GsonUtil.isJson(result)) {
logger.info("任务提交错误:{}", result);
return "error:" + result;
}
if (result == null) {
return "error:" + "livy地址:" + livyUri + "错误,请检查";
}
logger.info("提交返回任务返回信息:{}", result);
JSONObject jsonObject = JSONObject.parseObject(result);
String state = jsonObject.getString("state");
String id = jsonObject.getString("id");
Thread thread = new Thread(() -> {
try {
queryState(livyParam.getLivyUri(), id, state);
} catch (InterruptedException | IOException e) {
logger.error("线程运行出错:{}", e.fillInStackTrace());
}
}, livyParam.getName() + System.currentTimeMillis());
thread.start();
return result;
} //提交任务执行状态验证
public void queryState(String livyUrl, String batchId, String responseState) throws InterruptedException, IOException {
if (responseState != null && !FAIl_STATUS_LIST.contains(responseState)) {
boolean isRunning = true;
while (isRunning) {
String url = livyUrl + "/batches/" + batchId;
String batchesInfo = httpUtils.getAccess(url, headers);
JSONObject info = JSON.parseObject(batchesInfo);
String id = info.getString("id");
String sta = info.getString("state");
String appId = info.getString("appId");
String appInfo = info.getString("appInfo");
logger.info("livy:sessionId:{},state:{}", id, sta);
if ("success".equals(sta)) {
logger.info("任务{}:执行完成", appId, appInfo);
httpUtils.close();
isRunning = false;
} else if (FAIl_STATUS_LIST.contains(sta) || sta == null) {
logger.error("任务{}执行有误,请检查后重新提交:\n", appId, batchesInfo);
httpUtils.close();
isRunning = false;
} else if ("running".equals(sta) || "idle".equals(sta) || "starting".equals(sta)) {
logger.info("查看任务{},运行状态:\n{}", appId, batchesInfo);
} else {
logger.info("任务{}状态:{},未知,退出任务查看", id, sta);
isRunning = false;
}
Thread.sleep(5000);
}
}
}
}
livy请求参数
@Data
public class LivyParam {
/**
* livy的地址
*/
private String livyUri; /**
* 要运行的jar包路径
*/
private String file;
/**
* 运行的代理名
*/
private String proxyUser;
/**
* 运行主类
*/
private String className;
/**
* 主类的参数
*/
private List<String> args;
/**
* 需要运行的jar包
*/
private String thirdJarPath;
private List<String> jars;
private List<String> pyFiles;
private List<String> files;
private String driverMemory;
private Integer driverCores;
private String executorMemory;
private Integer executorCores;
private Integer numExecutors;
private List<String> archives;
/**
* 队列
*/
private String queue;
/**
* appName
*/
private String name;
/**
* 其他配置
*/
private Map<String, String> conf; }
测试
构建参数
new livyParam = new LivyParam();
livyParam.setLivyUri(sparkSubmitParam.getLivyUri());
livyParam.setClassName(sparkSubmitParam.getClassName());
livyParam.setArgs(sparkSubmitParam.getArgs());
livyParam.setConf(sparkSubmitParam.getConf());
livyParam.setDriverCores(sparkSubmitParam.getDriverCores());
livyParam.setDriverMemory(sparkSubmitParam.getDriverMemory());
livyParam.setArchives(sparkSubmitParam.getArchives());
livyParam.setExecutorCores(sparkSubmitParam.getExecutorCores());
livyParam.setExecutorMemory(sparkSubmitParam.getExecutorMemory());
livyParam.setJars(sparkSubmitParam.getJars());
livyParam.setFile(sparkSubmitParam.getFile());
livyParam.setName(sparkSubmitParam.getName());
livyParam.setQueue(sparkSubmitParam.getQueue());
livyParam.setProxyUser(sparkSubmitParam.getProxyUser()); //发送请求
String result = liveServer.batchSubmit(livyParam);
livy提交spark应用的更多相关文章
- Spark On Yarn:提交Spark应用程序到Yarn
转载自:http://lxw1234.com/archives/2015/07/416.htm 关键字:Spark On Yarn.Spark Yarn Cluster.Spark Yarn Clie ...
- 如何在Java应用中提交Spark任务?
最近看到有几个Github友关注了Streaming的监控工程--Teddy,所以思来想去还是优化下代码,不能让别人看笑话,是不.于是就想改在一下之前最丑陋的一个地方--任务提交 本博客内容基于Spa ...
- 利用SparkLauncher 类以JAVA API 编程的方式提交Spark job
一.环境说明和使用软件的版本说明: hadoop-version:hadoop-2.9.0.tar.gz spark-version:spark-2.2.0-bin-hadoop2.7.tgz jav ...
- 【Spark】提交Spark任务-ClassNotFoundException-错误处理
提交Spark任务-ClassNotFoundException-错误处理 Overview - Spark 2.2.0 Documentation Spark Streaming - Spark 2 ...
- Spark2.x(五十九):yarn-cluster模式提交Spark任务,如何关闭client进程?
问题: 最近现场反馈采用yarn-cluster方式提交spark application后,在提交节点机上依然会存在一个yarn的client进程不关闭,又由于spark application都是 ...
- Idea里面远程提交spark任务到yarn集群
Idea里面远程提交spark任务到yarn集群 1.本地idea远程提交到yarn集群 2.运行过程中可能会遇到的问题 2.1首先需要把yarn-site.xml,core-site.xml,hdf ...
- spark-submit提交spark任务的具体参数配置说明
spark-submit提交spark任务的具体参数配置说明 1.spark提交任务常见的两种模式 2.提交任务时的几个重要参数 3.参数说明 3.1 executor_cores*num_execu ...
- 提交Spark作业遇到的NoSuchMethodError问题总结
测试应用说明 测试的Spark应用实现了同步hive表到kafka的功能.具体处理流程: 从 ETCD 获取 SQL 语句和 Kafka 配置信息 使用 SparkSQL 读取 Hive 数据表 把 ...
- 基于Livy的Spark提交平台搭建与开发
为了方便使用Spark的同学提交任务以及加强任务管理等原因,经调研采用Livy比较靠谱,下图大致罗列一下几种提交平台的差别. 本文会以基于mac的单机环境搭建一套Spark+Livy+Hadoop来展 ...
随机推荐
- PyQt学习随笔:Qt事件类QEvent详解
QEvent类是PyQt5.QtCore中定义的事件处理的基类,事件对象包含了事件对应的参数. <Python & PyQt学习随笔:PyQt主程序的基本框架>介绍了PyQt程序通 ...
- PyQt(Python+Qt)学习随笔:部件的minimumSize、minimumSizeHint之间的区别与联系
1.minimumSize是一个部件设置的最小值,minimumSizeHint是部件Qt建议的最小值: 2.minimumSizeHint是必须在布局中的部件才有效,如果是窗口,必须窗口设置了布局才 ...
- idea2020.2.x/2020.3.x最新破解版方法教程无限永久重置插件激活码
idea是一个java开发工件,相信我所有的朋友都用过.本教程教你做到完美,安全,永久.破解 idea2020.2.x和idea2020.3.x的所有版本绝对是100% 激活,支持Windows Ma ...
- uniapp云打包配置讲解
HBuilderX开发工具,菜单栏:发行(U) → 原生App云打包(P) 安卓云打包配置: 云打包配置分为公共测试证书和自有证书. 云打包配置使用公共测试证书很简单,直接勾选后打包. 如果要测试第三 ...
- 用 shell 脚本做日志清洗
问题的提出 公司有一个用户行为分析系统,可以记录用户在使用公司产品过程中的一系列操作轨迹,便于分析产品使用情况以便优化产品 UI 界面布局.这套系统有点类似于 Google Analyse(GA),所 ...
- vue+axois 封装请求+拦截器(请求锁+统一错误)
需求 封装常用请求 拦截器-请求锁 统一处理错误码 一.封装常用的请求 解决痛点:不要每一个模块的api都还要写get,post,patch请求方法.直接将这些常用的方法封装好. 解决方案:写一个类 ...
- elasticsearch6.5.x-centos6
elasticsearch6.5.x-centos6 elasticsearch 和 关系型数据库中的类比 es ====== RDBMS index ----- database type ---- ...
- 用DirectX12绘制一个Cube
之前一篇文章讲了DirectX12的初始化流程,现在来看看在此基础上如何绘制一个Cube. 首先,我们要为这个Cube准备一个shader,来告诉GPU绘制的具体流程,DirectX中的shader使 ...
- vue实现点击样式高亮
•在data中定义即将渲染的数据,及active data() { return { active:'',//选中样式 }; }, 1 2 3 4 5 6 7 8 9 ...
- MySQL索引的使用是怎么样的?5个点轻松掌握!
一.前言 在MySQL中进行SQL优化的时候,经常会在一些情况下,对MySQL能否利用索引有一些迷惑. 譬如: MySQL 在遇到范围查询条件的时候就停止匹配了,那么到底是哪些范围条件? MySQL ...