如何使用Java调用CDM的Rest API创建数据迁移作业?
CDM提供了Rest API,可以通过程序调用实现自动化的作业创建或执行控制。
这里以CDM迁移MySQL数据库的表city1的数据到DWS的表city2为例,介绍如何使用Java调用CDM服务的REST API创建、启动、查询、删除该CDM作业。
- 云账号的用户名、账号名和项目ID。
- 创建一个CDM集群,并获取集群ID。
获取方法:在集群管理界面,单击CDM集群名称可查看集群ID,例如“c110beff-0f11-4e75-8b10-da7cd882b0ef”。
- 创建一个MySQL数据库和一个DWS数据库,并创建好表city1和表city2,创表语句如下:
MySQL: create table city1(code varchar(10),name varchar(32)); insert into city1 values('NY','New York'); DWS: create table city2(code varchar(10),name varchar(32));
- 在CDM集群下,创建连接到MySQL的连接,例如连接名称为“mysqltestlink”。创建连接到DWS的连接,例如连接名称为“dwstestlink”。
- 运行下述代码,依赖HttpClient包,建议使用4.5版本。Maven配置如下:
<project> <modelVersion>4.0.0</modelVersion> <groupId>cdm</groupId> <artifactId>cdm-client</artifactId> <version>1</version> <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5</version> </dependency> </dependencies> </project>
代码示例
使用Java调用CDM服务的REST API创建、启动、查询、删除CDM作业的代码示例如下:
package cdmclient; import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; 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.client.methods.HttpPut; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils;
public class CdmClient { private final static String DOMAIN_NAME="云账号名"; private final static String USER_NAME="云用户名"; private final static String USER_PASSWORD="云用户密码"; private final static String PROJECT_ID="项目ID"; private final static String CLUSTER_ID="CDM集群ID"; private final static String JOB_NAME="作业名称"; private final static String FROM_LINKNAME="源连接名称"; private final static String TO_LINKNAME="目的连接名称"; private final static String IAM_ENDPOINT="IAM的Endpoint"; private final static String CDM_ENDPOINT="CDM的Endpoint";
private CloseableHttpClient httpclient; private String token; public CdmClient() { this.httpclient = createHttpClient(); this.token = login(); } private CloseableHttpClient createHttpClient() { CloseableHttpClient httpclient =HttpClients.createDefault(); return httpclient; } private String login(){ HttpPost httpPost = new HttpPost("https://"+IAM_ENDPOINT+"/v3/auth/tokens"); String json = "{\r\n"+ "\"auth\": {\r\n"+ "\"identity\": {\r\n"+ "\"methods\": [\"password\"],\r\n"+ "\"password\": {\r\n"+ "\"user\": {\r\n"+ "\"name\": \""+USER_NAME+"\",\r\n"+ "\"password\": \""+USER_PASSWORD+"\",\r\n"+ "\"domain\": {\r\n"+ "\"name\": \""+DOMAIN_NAME+"\"\r\n"+ "}\r\n"+ "}\r\n"+ "}\r\n"+ "},\r\n"+ "\"scope\": {\r\n"+ "\"project\": {\r\n"+ "\"name\": \"PROJECT_NAME\"\r\n"+ "}\r\n"+ "}\r\n"+ "}\r\n"+ "}\r\n"; try { StringEntity s = new StringEntity(json); s.setContentEncoding("UTF-8"); s.setContentType("application/json"); httpPost.setEntity(s); CloseableHttpResponse response = httpclient.execute(httpPost); Header tokenHeader = response.getFirstHeader("X-Subject-Token"); String token = tokenHeader.getValue(); System.out.println("Login successful"); return token; } catch (Exception e) { throw new RuntimeException("login failed.", e); } }
/*创建作业*/ public void createJob(){ HttpPost httpPost = new HttpPost("https://"+CDM_ENDPOINT+"/cdm/v1.0/"+PROJECT_ID+"/clusters/"+CLUSTER_ID+"/cdm/job"); /**此处JSON信息比较复杂,可以先在作业管理界面上创建一个作业,然后单击作业后的“作业JSON定义”,复制其中的JSON内容,格式化为Java字符串语法,然后粘贴到此处。 *JSON消息体中一般只需要替换连接名、导入和导出的表名、导入导出表的字段列表、源表中用于分区的字段。**/ String json = "{\r\n"+ "\"jobs\": [\r\n"+ "{\r\n"+ "\"from-connector-name\": \"generic-jdbc-connector\",\r\n"+ "\"name\": \""+JOB_NAME+"\",\r\n"+ "\"to-connector-name\": \"generic-jdbc-connector\",\r\n"+ "\"driver-config-values\": {\r\n"+ "\"configs\": [\r\n"+ "{\r\n"+ "\"inputs\": [\r\n"+ "{\r\n"+ "\"name\": \"throttlingConfig.numExtractors\",\r\n"+ "\"value\": \"1\"\r\n"+ "}\r\n"+ "],\r\n"+ "\"validators\": [],\r\n"+ "\"type\": \"JOB\",\r\n"+ "\"id\": 30,\r\n"+ "\"name\": \"throttlingConfig\"\r\n"+ "}\r\n"+ "]\r\n"+ "},\r\n"+ "\"from-link-name\": \""+FROM_LINKNAME+"\",\r\n"+ "\"from-config-values\": {\r\n"+ "\"configs\": [\r\n"+ "{\r\n"+ "\"inputs\": [\r\n"+ "{\r\n"+ "\"name\": \"fromJobConfig.schemaName\",\r\n"+ "\"value\": \"sqoop\"\r\n"+ "},\r\n"+ "{\r\n"+ "\"name\": \"fromJobConfig.tableName\",\r\n"+ "\"value\": \"city1\"\r\n"+ "},\r\n"+ "{\r\n"+ "\"name\": \"fromJobConfig.columnList\",\r\n"+ "\"value\": \"code&name\"\r\n"+ "},\r\n"+ "{\r\n"+ "\"name\": \"fromJobConfig.partitionColumn\",\r\n"+ "\"value\": \"code\"\r\n"+ "}\r\n"+ "],\r\n"+ "\"validators\": [],\r\n"+ "\"type\": \"JOB\",\r\n"+ "\"id\": 7,\r\n"+ "\"name\": \"fromJobConfig\"\r\n"+ "}\r\n"+ "]\r\n"+ "},\r\n"+ "\"to-link-name\": \""+TO_LINKNAME+"\",\r\n"+ "\"to-config-values\": {\r\n"+ "\"configs\": [\r\n"+ "{\r\n"+ "\"inputs\": [\r\n"+ "{\r\n"+ "\"name\": \"toJobConfig.schemaName\",\r\n"+ "\"value\": \"sqoop\"\r\n"+ "},\r\n"+ "{\r\n"+ "\"name\": \"toJobConfig.tableName\",\r\n"+ "\"value\": \"city2\"\r\n"+ "},\r\n"+ "{\r\n"+ "\"name\": \"toJobConfig.columnList\",\r\n"+ "\"value\": \"code&name\"\r\n"+ "}, \r\n"+ "{\r\n"+ "\"name\": \"toJobConfig.shouldClearTable\",\r\n"+ "\"value\": \"true\"\r\n"+ "}\r\n"+ "],\r\n"+ "\"validators\": [],\r\n"+ "\"type\": \"JOB\",\r\n"+ "\"id\": 9,\r\n"+ "\"name\": \"toJobConfig\"\r\n"+ "}\r\n"+ "]\r\n"+ "}\r\n"+ "}\r\n"+ "]\r\n"+ "}\r\n"; try { StringEntity s = new StringEntity(json); s.setContentEncoding("UTF-8"); s.setContentType("application/json"); httpPost.setEntity(s); httpPost.addHeader("X-Auth-Token", this.token); httpPost.addHeader("X-Language", "en-us"); CloseableHttpResponse response = httpclient.execute(httpPost); int status = response.getStatusLine().getStatusCode(); if(status == 200){ System.out.println("Create job successful."); }else{ System.out.println("Create job failed."); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Create job failed.", e); } }
/*启动作业*/ public void startJob(){ HttpPut httpPut = new HttpPut("https://"+CDM_ENDPOINT+"/cdm/v1.0/"+PROJECT_ID+"/clusters/"+CLUSTER_ID+"/cdm/job/"+JOB_NAME+"/start"); String json = ""; try { StringEntity s = new StringEntity(json); s.setContentEncoding("UTF-8"); s.setContentType("application/json"); httpPut.setEntity(s); httpPut.addHeader("X-Auth-Token", this.token); httpPut.addHeader("X-Language", "en-us"); CloseableHttpResponse response = httpclient.execute(httpPut); int status = response.getStatusLine().getStatusCode(); if(status == 200){ System.out.println("Start job successful."); }else{ System.out.println("Start job failed."); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Start job failed.", e); } }
/*循环查询作业运行状态,直到作业运行结束。*/ public void getJobStatus(){ HttpGet httpGet = new HttpGet("https://"+CDM_ENDPOINT+"/cdm/v1.0/"+PROJECT_ID+"/clusters/"+CLUSTER_ID+"/cdm/job/"+JOB_NAME+"/status"); try { httpGet.addHeader("X-Auth-Token", this.token); httpGet.addHeader("X-Language", "en-us"); boolean flag = true; while(flag){ CloseableHttpResponse response = httpclient.execute(httpGet); int status = response.getStatusLine().getStatusCode(); if(status == 200){ HttpEntity entity = response.getEntity(); String msg = EntityUtils.toString(entity); if(msg.contains("\"status\":\"SUCCEEDED\"")){ System.out.println("Job succeeded"); break; }else if (msg.contains("\"status\":\"FAILED\"")){ System.out.println("Job failed."); break; }else{ Thread.sleep(1000); } }else{ System.out.println("Get job status failed."); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); break; } } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Get job status failed.", e); } }
/*删除作业*/ public void deleteJob(){ HttpDelete httpDelte = new HttpDelete("https://"+CDM_ENDPOINT+"/cdm/v1.0/"+PROJECT_ID+"/clusters/"+CLUSTER_ID+"/cdm/job/"+JOB_NAME); try { httpDelte.addHeader("X-Auth-Token", this.token); httpDelte.addHeader("X-Language", "en-us"); CloseableHttpResponse response = httpclient.execute(httpDelte); int status = response.getStatusLine().getStatusCode(); if(status == 200){ System.out.println("Delete job successful."); }else{ System.out.println("Delete job failed."); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Delete job failed.", e); } }
/*关闭*/ public void close(){ try { httpclient.close(); } catch (IOException e) { throw new RuntimeException("Close failed.", e); } } public static void main(String[] args){ CdmClient cdmClient = new CdmClient(); cdmClient.createJob(); cdmClient.startJob(); cdmClient.getJobStatus(); cdmClient.deleteJob(); cdmClient.close(); } }