基于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. Raspberry pi 上部署调试.Net的IoT程序

    树莓派(Raspberry pi)是一款基于ARM 架构的单板计算机(Single Board Computer),可以运行各种 Linux 操作系统,其官方推荐使用的 Raspberry Pi OS ...

  2. 记录使用socket.io的使用

    今天记录一下node.js的egg框架搭建的socket.io,前端联合使用 首先得引入socket.io的js,我这边是用的下载到本地的一个js 引入:const io = require('../ ...

  3. Solution Set - Codeforces Global Round 1~8

    目录 Codeforces Global Round 1 A. Parity B. Tape C. Meaningless Operations D. Jongmah E. Magic Stones ...

  4. SpringBoot集成EasyExcel

    EasyExcel是阿里巴巴开源poi插件之一,主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错.主要解决方式:通过解压文件的方式加载,一行一 ...

  5. WebSocket详解:技术原理、代码演示和应用案例

    1.内容简介 本文将简要介绍 WebSocket 的由来.原理机制以及服务端/客户端实现,并以实际客户案例指导并讲解了如何使用 WebSocket 解决实时响应及服务端消息推送方面的问题.本文适用于熟 ...

  6. Kotlin:【初始化】主构造函数、在主构造函数里定义属性、次构造函数、默认参数、初始化块、初始化顺序

  7. LeetCode刷题:AddressSanitizer: heap-buffer-overflow问题请教||全局变量和引用传递的区别

    在刷 https://leetcode.cn/problems/sudoku-solver/description/ 遇到AddressSanitizer: heap-buffer-overflow的 ...

  8. 将文件转换为文件流进行上传(例:通过HDMI进行传输)

    package com.boottest.app; import org.apache.commons.codec.Charsets; import org.apache.http.HttpEntit ...

  9. yum repo和rpm,添加阿里repos

    RPMRPM(Red-hat Package Manager),是一个由红帽最早开发出来的包管理器,目前已经是大多数Linux发行的默认包管理器.RPM管理的包都是以.rpm结尾,其中存储了该软件的安 ...

  10. 具体数学第六章习题选做(genshining)

    11.对于 \(n\ge 0\),求以下式子的封闭形式. \[\sum_k(-1)^k{n\brack k} \] 由于 \[\sum{n\brack k}x^k=x^{\overline n} \] ...