基于Linkis的Rest-API调用任务

官网示例:“https://linkis.apache.org/zh-CN/docs/1.3.2/api/linkis-task-operator”

集合Springboot集成

准备工作:SpringBoot-web应用:封装好支持cookie的restClient就行

封装RestTemplate

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate; /**
* @author 白嫖老郭
* @createTime 2024-02-26
* @description RestTemplate封装对象的配置与注入
*/
@Configuration
public class RestClientConfig { @Value("${restTemplate.thread.maxTotal:200}")
private int maxTotal;
@Value("${restTemplate.thread.maxPerRoute:100}")
private int maxPerRoute;
@Value("${restTemplate.request.socketTimeout:10000}")
private int socketTimeout;
@Value("${restTemplate.request.connectTimeout:2000}")
private int connectTimeout;
@Value("${restTemplate.request.connectionRequestTimeout:2000}")
private int connectionRequestTimeout; @Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
return restTemplate;
} private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient());
return factory;
} private HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
// Set max total connection
connectionManager.setMaxTotal(maxTotal);
// Set max route connection
connectionManager.setDefaultMaxPerRoute(maxPerRoute); RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.build();
return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
} }

编写封装调用Links任务的接口

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap; /**
* 调用底层Linkis执行数据质量分析----调用Spark执行Shell-SQL
*/
@RestController
public class RestControllerLinkis { Logger logger = LoggerFactory.getLogger(RestControllerLinkis.class); // 注入RestTemplate实例
@Autowired
private RestTemplate restTemplate; @Value("${linkis.url:http://10.130.1.37:8188}")
private String linkisUrl; private String sqlSimpleOne = "select count(*) from default.student where (name='zhangsan') and (sex is null)";
private String sqlSimpleTwo = "select count(*) from default.student where (name='lisi') and (sex is null)";
private String sqlSimpleThree = "select * from default.student where (name = 'zhangsan' or name = 'lisi') and (sex is null)"; /**
* (1)登录并执行任务
*
* @param httpServletRequest httpServletRequest
* @param httpServletResponse httpServletResponse
* @return ResponseEntity
* @throws Exception
*/
@GetMapping("/executeSql")
public ResponseEntity<JSONObject> loginAndExecuteSql(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String sql = httpServletRequest.getParameter("sql");
String executeSql = "";
if (StringUtils.isNotBlank(sql)) {
switch (sql) {
case "one":
executeSql = sqlSimpleOne;
break;
case "two":
executeSql = sqlSimpleTwo;
break;
case "three":
executeSql = sqlSimpleThree;
break;
default:
executeSql = sqlSimpleOne;
break;
}
}
logger.error("============================================================");
ResponseEntity<JSONObject> login = login(restTemplate);
logger.info(login.getBody().toJSONString());
logger.error("============================================================");
ResponseEntity<JSONObject> responseEntity = executeSql(restTemplate, executeSql);
Long taskID = responseEntity.getBody().getJSONObject("data").getLong("taskID");
logger.error("========================TASKID====================================");
logger.info(taskID.toString());
return responseEntity;
} /**
* (3)获取执行结果:
*
* @param httpServletRequest
* @param httpServletResponse
* @return
* @throws Exception
*/
@GetMapping("/getResult")
public ResponseEntity<JSONObject> getResult(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 获取任务的保存路径
String resultLocation = getFIleURL(restTemplate, httpServletRequest.getParameter("taskID"));
// 下载保存路径·下文件的类型
String resUrl = linkisUrl + "/api/rest_j/v1/filesystem/openFile?path=" + resultLocation + "/_0.dolphin";
ResponseEntity<JSONObject> resResp = restTemplate.getForEntity(resUrl, JSONObject.class);
if (resResp != null && resResp.getStatusCode().value() == HttpStatus.SC_OK) {
//do something
JSONObject body = resResp.getBody();
assert body != null;
System.out.println(body.toJSONString());
}
return resResp;
} /**
* (4)获取执行日志:
*
* @param httpServletRequest
* @param httpServletResponse
* @return
* @throws Exception
*/
@GetMapping("/getExecuteLog")
public ResponseEntity<JSONObject> getExecuteLog(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 获取任务的执行ID
String execID = httpServletRequest.getParameter("execID");
// 下获取执行日志
String resUrl = linkisUrl + "/api/rest_j/v1/entrance/" + execID + "/log?fromLine=0&size=500";
ResponseEntity<JSONObject> resResp = restTemplate.getForEntity(resUrl, JSONObject.class);
if (resResp != null && resResp.getStatusCode().value() == HttpStatus.SC_OK) {
//do something
JSONObject body = resResp.getBody();
assert body != null;
System.out.println(body.toJSONString());
}
return resResp;
} /**
* (5)终止任务:
*
* @param httpServletRequest
* @param httpServletResponse
* @return
* @throws Exception
*/
@GetMapping("/killExecuteTask")
public ResponseEntity<JSONObject> killExecuteTask(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 获取任务的执行ID
String execID = httpServletRequest.getParameter("execID");
// 终止任务
String resUrl = linkisUrl + "/api/rest_j/v1/entrance/" + execID + "/kill";
ResponseEntity<JSONObject> resResp = restTemplate.getForEntity(resUrl, JSONObject.class);
if (resResp != null && resResp.getStatusCode().value() == HttpStatus.SC_OK) {
//do something
JSONObject body = resResp.getBody();
assert body != null;
System.out.println(body.toJSONString());
}
return resResp;
} /**
* (2)获取执行结果的的状态
*
* @param httpServletRequest
* @param httpServletResponse
* @return
* @throws Exception
*/
@GetMapping("/getStatus")
public ResponseEntity<JSONObject> getStatus(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String execID = httpServletRequest.getParameter("execID");
String statusUrl = linkisUrl + "/api/rest_j/v1/entrance/" + execID + "/status";
ResponseEntity<JSONObject> statusResp = restTemplate.getForEntity(statusUrl, JSONObject.class);
if (statusResp != null && statusResp.getStatusCode().value() == HttpStatus.SC_OK) {
String status;
for (; ; ) {
// 睡眠6秒钟
Thread.sleep(6000);
// 持续刷新状态
statusResp = restTemplate.getForEntity(statusUrl, JSONObject.class);
status = statusResp.getBody().getJSONObject("data").getString("status");
//死循环查看任务状态,如果任务成功或者失败,则退出循环
if ("Succeed".equals(status) || "Failed".equals(status)) {
break;
}
}
if ("Succeed".equals(status)) {
// do something
logger.error("=========================================状态执行成功=========================================");
}
}
return statusResp;
} private ResponseEntity<JSONObject> login(RestTemplate restClient) {
JSONObject postData = new JSONObject();
postData.put("userName", "hadoop");
postData.put("password", "f45b9a1af");
String loginUrl = linkisUrl + "/api/rest_j/v1/user/login";
return restClient.postForEntity(loginUrl, postData, JSONObject.class);
} /**
* @param restClient
* @param sql 要执行的sql代码
* @return
*/
private ResponseEntity<JSONObject> executeSql(RestTemplate restClient, String sql) {
String url = "/api/rest_j/v1/entrance/execute";
JSONObject map = new JSONObject();
map.put("method", url);
map.put("params", new HashMap<>()); //用户指定的运行服务程序的参数,必填,里面的值可以为空
map.put("executeApplicationName", "spark");//执行引擎,我用的hive
map.put("executionCode", sql);
map.put("runType", "sql");//当用户执行如spark服务时,可以选择python、R、SQL等,不能为空
//因为我没有执行文件脚本,所以没有scriptPath参数
String executeSql = linkisUrl + url;
return restClient.postForEntity(executeSql, map, JSONObject.class);
} /**
* @param restClient
* @param taskID 要执行的sql代码
* @return
*/
private String getFIleURL(RestTemplate restClient, String taskID) {
String historyUrl = "/api/rest_j/v1/jobhistory/" + taskID + "/get";
String executeSql = linkisUrl + historyUrl;
ResponseEntity<JSONObject> hisResp = restClient.getForEntity(executeSql, JSONObject.class);
String resultLocation = null;
logger.info(hisResp.getBody().toJSONString());
if (hisResp != null && hisResp.getStatusCode().value() == HttpStatus.SC_OK) {
resultLocation = hisResp.getBody().getJSONObject("data").getJSONObject("task").getString("resultLocation");
}
return resultLocation;
} /**
* @param restClient
* @param resultLocation 要执行的sql代码
* @return
*/
private String getRestFileMsg(RestTemplate restClient, String resultLocation) {
String resUrl = "/api/rest_j/v1/filesystem/openFile?path=" + resultLocation + "/_0.dolphin";
String executeSql = linkisUrl + resUrl;
ResponseEntity<JSONObject> resResp = restClient.getForEntity(executeSql, JSONObject.class);
if (resResp != null && resResp.getStatusCode().value() == HttpStatus.SC_OK) {
//do something
JSONObject body = resResp.getBody();
logger.info(body.toJSONString());
}
logger.error("ending==========================");
return resultLocation;
} }

测试验证

执行任务

查询任务状态

查询任务结果

查询任务日志

到Linkis管理台查询任务

。。。。。。SayGoodBye......

SpringBoot应用调用Linkis进行任务调度执行SQl;进行数据质量分析的更多相关文章

  1. SpringBoot 设置服务一启动就执行、初始化数据

    定义一个类实现ApplicationRunner接口,然后Override这个ApplicationRunner接口的run方法 @Component public class TaskRunner ...

  2. NHibernate直接执行SQL进行插入

    有时候,需要用NHibernate直接执行SQL进行数据insert或update. 怎么写呢?简单一点的,可以直接拼凑出来的SQL,这样写: using NHibernate; StringBuil ...

  3. AngularJS SQL 获取数据

    使用PHP从MySQL中获取数据: <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  4. Oracle sql共享池$sqlarea分析SQL资源使用情况

    遇到需要排查一个系统使用sql的情况,可以通过查询Oracle的$sql.$ssssion.$sqlarea进行统计排查 排查时可以先看一下$sql和$session的基本信息 select * fr ...

  5. 详解SQL Server数据修复命令DBCC的使用

    严重级别为 21 表示可能存在数据损坏. 可能的原因包括损坏的页链.损坏的 IAM 或该对象的 sys.objects目录视图中存在无效条目. 这些错误通常由硬件或磁盘设备驱动程序故障而引起. MS ...

  6. springboot中使用mybatis显示执行sql

    springboot 中使用mybatis显示执行sql的配置,在properties中添加如下 logging.你的包名=debug 2018-11-27 16:35:43.044 [DubboSe ...

  7. spring-boot启动自动执行sql文件失效 解决办法

    在springboot1.5及以前的版本,要执行sql文件只需在applicaion文件里指定sql文件的位置即可.但是到了springboot2.x版本, 如果只是这样做的话springboot不会 ...

  8. Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)

    上一篇我们分析了Mapper接口代理类的生成,本篇接着分析是如何调用到XML中的SQL 我们回顾一下MapperMethod 的execute方法 public Object execute(SqlS ...

  9. Mybaits 源码解析 (七)----- Select 语句的执行过程分析(下篇)(Mapper方法是如何调用到XML中的SQL的?)全网最详细,没有之一

    我们上篇文章讲到了查询方法里面的doQuery方法,这里面就是调用JDBC的API了,其中的逻辑比较复杂,我们这边文章来讲,先看看我们上篇文章分析的地方 SimpleExecutor public & ...

  10. shell调用sqlplus批量执行sql文件

    在最近的工作中,经常需要批量执行一些DML, DDL, PL/SQL语句或导入一些Function, Procedure.因为support的国家比较多,常常需要一个登陆到一个国家的数据库上执行完成后 ...

随机推荐

  1. Object.freeze冻结属性和v-if结合requestAnimationFrame分帧渲染解决白屏

    计算100W条数据的长度造成2s延迟 <template> <div> <h1>数据总长度{{ arrList.length }}</h1> </ ...

  2. HUAWEI MindStudio安装配置

    HUAWEI MindStudio安装配置 官网: 链接 安装流程 获取软件包 软件包 说明 获取链接 MindStudio_{version}_linux.tar.gz MindStudio软件包, ...

  3. 在 Vercel 部署随机图 API

    在本文中,将详细介绍如何在 Vercel 平台上部署一个具有分类功能的随机图片 API.通过这个 API,用户可以根据不同的分类获取随机图片链接,并且还可以从所有分类中随机获取一张图片. 项目结构 首 ...

  4. UWP 读写文件

    List<Pics> pics = new List<Pics>(); for (int i = 0; i < 2000; i++) { pics.Add(new Pic ...

  5. Kubernetes Pod状态和生命周期管理

    ​Pod​​​是​​kubernetes​​​中你可以创建和部署的最小也是最简的单位.​​Pod​​代表着集群中运行的进程. ​​Pod​​​中封装着应用的容器(有的情况下是好几个容器),存储.独立的 ...

  6. ffmpeg简易播放器(4)--使用SDL播放音频

    SDL(英语:Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发函数库,使用C语言写成.SDL提供了数种控制图像.声音.输出入的函数,让开发者只要用相同或是相似的代码 ...

  7. 小程序之confirm-type改变键盘右下角的内容和input按钮详解

    confirm-type的介绍 confirm-type 在什么时候使用呢? 如果说搜索框的时候,当用户输入完了之后,我们就需要 将confirm-type="search"的值设 ...

  8. 两种方式让你用Python轻松在RDKX5上部署推理

    作者:SkyXZ CSDN:SkyXZ--CSDN博客 博客园:SkyXZ - 博客园 宿主机环境:WSL2-Ubuntu22.04+Cuda12.6.D-Robotics-OE 1.2.8.Ubun ...

  9. redis 执行性能检测指令报错:-bash: redis-benchmark: command not found

    最近在看redis相关的内容,redis有自带检测性能的命令: -bash: redis-benchmark: command not found 碰到的所有资料中均提示不能在redis客户端中执行, ...

  10. 操作系统发展历史与Linux

    操作系统发展历史与Linux 随着计算机技术的迅猛发展,操作系统作为计算机系统的核心软件,经历了从单一到多样.从封闭到开放的演变过程.从最初的批处理系统,到分时操作系统的兴起,再到个人计算机操作系统的 ...