![JAR search and dependency download from the Maven repository](/logo.png)
com.github.ltsopensource.jobclient.JobClient Maven / Gradle / Ivy
package com.github.ltsopensource.jobclient;
import com.github.ltsopensource.core.AppContext;
import com.github.ltsopensource.core.cluster.AbstractClientNode;
import com.github.ltsopensource.core.commons.utils.Assert;
import com.github.ltsopensource.core.commons.utils.BatchUtils;
import com.github.ltsopensource.core.commons.utils.CollectionUtils;
import com.github.ltsopensource.core.commons.utils.StringUtils;
import com.github.ltsopensource.core.constant.Constants;
import com.github.ltsopensource.core.domain.Job;
import com.github.ltsopensource.core.exception.JobSubmitException;
import com.github.ltsopensource.core.exception.JobTrackerNotFoundException;
import com.github.ltsopensource.core.logger.Logger;
import com.github.ltsopensource.core.logger.LoggerFactory;
import com.github.ltsopensource.core.protocol.JobProtos;
import com.github.ltsopensource.core.protocol.command.CommandBodyWrapper;
import com.github.ltsopensource.core.protocol.command.JobCancelRequest;
import com.github.ltsopensource.core.protocol.command.JobSubmitRequest;
import com.github.ltsopensource.core.protocol.command.JobSubmitResponse;
import com.github.ltsopensource.jobclient.domain.JobClientAppContext;
import com.github.ltsopensource.jobclient.domain.JobClientNode;
import com.github.ltsopensource.jobclient.domain.Response;
import com.github.ltsopensource.jobclient.domain.ResponseCode;
import com.github.ltsopensource.jobclient.processor.RemotingDispatcher;
import com.github.ltsopensource.jobclient.support.*;
import com.github.ltsopensource.remoting.AsyncCallback;
import com.github.ltsopensource.remoting.RemotingProcessor;
import com.github.ltsopensource.remoting.ResponseFuture;
import com.github.ltsopensource.remoting.protocol.RemotingCommand;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* @author Robert HG ([email protected]) on 7/25/14.
* 任务客户端
*/
public class JobClient extends
AbstractClientNode {
protected static final Logger LOGGER = LoggerFactory.getLogger(JobClient.class);
private static final int BATCH_SIZE = 10;
// 过载保护的提交者
private JobSubmitProtector protector;
protected JobClientMStatReporter stat;
public JobClient() {
this.stat = new JobClientMStatReporter(appContext);
// 监控中心
appContext.setMStatReporter(stat);
}
@Override
protected void beforeStart() {
appContext.setRemotingClient(remotingClient);
protector = new JobSubmitProtector(appContext);
}
@Override
protected void afterStart() {
appContext.getMStatReporter().start();
}
@Override
protected void afterStop() {
appContext.getMStatReporter().stop();
}
@Override
protected void beforeStop() {
}
public Response submitJob(Job job) throws JobSubmitException {
checkStart();
return protectSubmit(Collections.singletonList(job));
}
private Response protectSubmit(List jobs) throws JobSubmitException {
return protector.execute(jobs, new JobSubmitExecutor() {
@Override
public Response execute(List jobs) throws JobSubmitException {
return submitJob(jobs, SubmitType.ASYNC);
}
});
}
/**
* 取消任务
*/
public Response cancelJob(String taskId, String taskTrackerNodeGroup) {
checkStart();
final Response response = new Response();
Assert.hasText(taskId, "taskId can not be empty");
Assert.hasText(taskTrackerNodeGroup, "taskTrackerNodeGroup can not be empty");
JobCancelRequest request = CommandBodyWrapper.wrapper(appContext, new JobCancelRequest());
request.setTaskId(taskId);
request.setTaskTrackerNodeGroup(taskTrackerNodeGroup);
RemotingCommand requestCommand = RemotingCommand.createRequestCommand(
JobProtos.RequestCode.CANCEL_JOB.code(), request);
try {
RemotingCommand remotingResponse = remotingClient.invokeSync(requestCommand);
if (JobProtos.ResponseCode.JOB_CANCEL_SUCCESS.code() == remotingResponse.getCode()) {
LOGGER.info("Cancel job success taskId={}, taskTrackerNodeGroup={} ", taskId, taskTrackerNodeGroup);
response.setSuccess(true);
return response;
}
response.setSuccess(false);
response.setCode(JobProtos.ResponseCode.valueOf(remotingResponse.getCode()).name());
response.setMsg(remotingResponse.getRemark());
LOGGER.warn("Cancel job failed: taskId={}, taskTrackerNodeGroup={}, msg={}", taskId,
taskTrackerNodeGroup, remotingResponse.getRemark());
return response;
} catch (JobTrackerNotFoundException e) {
response.setSuccess(false);
response.setCode(ResponseCode.JOB_TRACKER_NOT_FOUND);
response.setMsg("Can not found JobTracker node!");
return response;
}
}
private void checkFields(List jobs) {
// 参数验证
if (CollectionUtils.isEmpty(jobs)) {
throw new JobSubmitException("Job can not be null!");
}
for (Job job : jobs) {
if (job == null) {
throw new JobSubmitException("Job can not be null!");
} else {
job.checkField();
}
}
}
protected Response submitJob(final List jobs, SubmitType type) throws JobSubmitException {
// 检查参数
checkFields(jobs);
final Response response = new Response();
try {
JobSubmitRequest jobSubmitRequest = CommandBodyWrapper.wrapper(appContext, new JobSubmitRequest());
jobSubmitRequest.setJobs(jobs);
RemotingCommand requestCommand = RemotingCommand.createRequestCommand(
JobProtos.RequestCode.SUBMIT_JOB.code(), jobSubmitRequest);
SubmitCallback submitCallback = new SubmitCallback() {
@Override
public void call(RemotingCommand responseCommand) {
if (responseCommand == null) {
response.setFailedJobs(jobs);
response.setSuccess(false);
response.setMsg("Submit Job failed: JobTracker is broken");
LOGGER.warn("Submit Job failed: {}, {}", jobs, "JobTracker is broken");
return;
}
if (JobProtos.ResponseCode.JOB_RECEIVE_SUCCESS.code() == responseCommand.getCode()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Submit Job success: {}", jobs);
}
response.setSuccess(true);
return;
}
// 失败的job
JobSubmitResponse jobSubmitResponse = responseCommand.getBody();
response.setFailedJobs(jobSubmitResponse.getFailedJobs());
response.setSuccess(false);
response.setCode(JobProtos.ResponseCode.valueOf(responseCommand.getCode()).name());
response.setMsg("Submit Job failed: " + responseCommand.getRemark() + " " + jobSubmitResponse.getMsg());
LOGGER.warn("Submit Job failed: {}, {}, {}", jobs, responseCommand.getRemark(), jobSubmitResponse.getMsg());
}
};
if (SubmitType.ASYNC.equals(type)) {
asyncSubmit(requestCommand, submitCallback);
} else {
syncSubmit(requestCommand, submitCallback);
}
} catch (JobTrackerNotFoundException e) {
response.setSuccess(false);
response.setCode(ResponseCode.JOB_TRACKER_NOT_FOUND);
response.setMsg("Can not found JobTracker node!");
} catch (Exception e) {
response.setSuccess(false);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setMsg(StringUtils.toString(e));
} finally {
// 统计
if (response.isSuccess()) {
stat.incSubmitSuccessNum(jobs.size());
} else {
stat.incSubmitFailedNum(CollectionUtils.sizeOf(response.getFailedJobs()));
}
}
return response;
}
/**
* 异步提交任务
*/
private void asyncSubmit(RemotingCommand requestCommand, final SubmitCallback submitCallback)
throws JobTrackerNotFoundException {
final CountDownLatch latch = new CountDownLatch(1);
remotingClient.invokeAsync(requestCommand, new AsyncCallback() {
@Override
public void operationComplete(ResponseFuture responseFuture) {
try {
submitCallback.call(responseFuture.getResponseCommand());
} finally {
latch.countDown();
}
}
});
try {
latch.await(Constants.LATCH_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new JobSubmitException("Submit job failed, async request timeout!", e);
}
}
/**
* 同步提交任务
*/
private void syncSubmit(RemotingCommand requestCommand, final SubmitCallback submitCallback)
throws JobTrackerNotFoundException {
submitCallback.call(remotingClient.invokeSync(requestCommand));
}
public Response submitJob(List jobs) throws JobSubmitException {
checkStart();
final Response response = new Response();
response.setSuccess(true);
int size = jobs.size();
BatchUtils.batchExecute(size, BATCH_SIZE, jobs, new BatchUtils.Executor() {
@Override
public boolean execute(List list) {
Response subResponse = protectSubmit(list);
if (!subResponse.isSuccess()) {
response.setSuccess(false);
response.addFailedJobs(list);
response.setMsg(subResponse.getMsg());
}
return true;
}
});
return response;
}
@Override
protected RemotingProcessor getDefaultProcessor() {
return new RemotingDispatcher(appContext);
}
/**
* 设置任务完成接收器
*/
public void setJobCompletedHandler(JobCompletedHandler jobCompletedHandler) {
appContext.setJobCompletedHandler(jobCompletedHandler);
}
enum SubmitType {
SYNC, // 同步
ASYNC // 异步
}
private void checkStart() {
if (!started.get()) {
throw new JobSubmitException("JobClient did not started");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy