com.alibaba.dts.client.service.NodeServerServiceImpl Maven / Gradle / Ivy
package com.alibaba.dts.client.service;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.alibaba.dts.client.executor.grid.unit.FlexibleThreadPoolExecutor;
import org.springframework.util.CollectionUtils;
import com.alibaba.dts.client.executor.grid.queue.receive.TaskReceiveHandler;
import com.alibaba.dts.client.executor.job.context.ClientContextImpl;
import com.alibaba.dts.client.store.access.TaskSnapshotAccess;
import com.alibaba.dts.common.constants.Constants;
import com.alibaba.dts.common.context.InvocationContext;
import com.alibaba.dts.common.domain.ExecutableTask;
import com.alibaba.dts.common.domain.remoting.RemoteMachine;
import com.alibaba.dts.common.domain.result.Result;
import com.alibaba.dts.common.domain.result.ResultCode;
import com.alibaba.dts.common.domain.store.ExecutionCounter;
import com.alibaba.dts.common.domain.store.TaskSnapshot;
import com.alibaba.dts.common.exception.AccessException;
import com.alibaba.dts.common.logger.SchedulerXLoggerFactory;
import com.alibaba.dts.common.logger.innerlog.Logger;
import com.alibaba.dts.common.service.NodeServerService;
import com.alibaba.dts.common.util.NamedThreadFactory;
/**
* @author Ronan Zhan
* @date 16/8/30.
*/
public class NodeServerServiceImpl implements NodeServerService {
private static final Logger logger = SchedulerXLoggerFactory.getLogger(NodeServerServiceImpl.class);
private final ConcurrentHashMap logTable = new ConcurrentHashMap();
private ClientContextImpl clientContext;
private BlockingQueue taskReceiveBuffer;
TaskReceiveHandler taskReceiveHandler;
private int bufferSize;
/**
* map for job instance and consume thread pool
*/
private ConcurrentHashMap executorServiceMap
= new ConcurrentHashMap();
/**
* 本机连接的node
*/
private final ConcurrentHashMap connectToNodes
= new ConcurrentHashMap();
/**
* 连接到本机的node
*/
private final ConcurrentHashMap connectFromNodes
= new ConcurrentHashMap();
public NodeServerServiceImpl(ClientContextImpl clientContext) {
this.clientContext = clientContext;
}
public void init() {
bufferSize = clientContext.nodeConfig.getReceiveBufferSize();
taskReceiveBuffer = new ArrayBlockingQueue(bufferSize);
taskReceiveHandler = new TaskReceiveHandler(clientContext, executorServiceMap);
taskReceiveHandler.listen(taskReceiveBuffer);
}
@Override
public Result connect() {
// RemoteMachine remoteMachine = InvocationContext.acquireRemoteMachine();
return new Result(true, ResultCode.SUCCESS);
}
@Override
public Result receiveTasks(final ExecutableTask executableTask) {
try {
final Long jobInstanceId = executableTask.getJobInstanceSnapshot().getId();
if (clientContext.getGridJobManager().containsInterruptedJobInstance(jobInstanceId)) {
logger.warn("[NodeServerService]: receiveTasks force interrupt:"
+ ",jobId:" + executableTask.getJob().getId()
+ ",jobInstanceId:" + executableTask.getJobInstanceSnapshot().getId()
+ ",total tasks:" + executableTask.getTaskSnapshotList().size()
);
return new Result(true, ResultCode.FAILURE);
}
ExecutorService executorService = executorServiceMap.get(jobInstanceId);
if (executorService == null) {
int consumerThreads = this.clientContext.getClientConfig().getConsumerThreads();
Map consumerThreadsMap = this.clientContext.getClientConfig().getConsumerThreadsMap();
if (!CollectionUtils.isEmpty(consumerThreadsMap) && consumerThreadsMap.get(
executableTask.getJob().getJobProcessor()) != null) {
consumerThreads = this.clientContext.getClientConfig().checkConsumerThreads(
consumerThreadsMap.get(executableTask.getJob().getJobProcessor()).intValue());
}
executorService = new FlexibleThreadPoolExecutor(consumerThreads, consumerThreads, 15, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("SchedulerX-Grid-Task-Processor_" + executableTask.getJob().getId() + "_" + jobInstanceId + "_" + executableTask.getJobInstanceSnapshot().getFireTime() + "#"));
ExecutorService executorServiceExist = executorServiceMap.putIfAbsent(jobInstanceId, executorService);
if (executorServiceExist != null) {
executorService.shutdownNow();
}
}
boolean publishEventResult = taskReceiveBuffer.offer(executableTask);
if (publishEventResult) {
return new Result(true, ResultCode.SUCCESS);
} else {
return new Result(false, ResultCode.NODE_RECEIVE_QUEUE_NOT_AVAILABLE);
}
} catch (Exception e) {
logger.error("Job接收错误, {}", executableTask, e);
return new Result(false);
}
}
/**
* 任务执行确认
*
* taskSnapshot
*/
@Override
public Result acknowledge(TaskSnapshot taskSnapshot) {
try {
RemoteMachine remoteMachine = InvocationContext.acquireRemoteMachine();
if (taskSnapshot.getStatus() == Constants.TASK_STATUS_SUCCESS
|| taskSnapshot.getStatus() == Constants.TASK_STATUS_FAILURE && taskSnapshot.getRetryCount() <= 0) {
int deletedCount = clientContext.getStore().getTaskSnapshotDao().delete(taskSnapshot);
if (deletedCount
<= 0) { //indicates that this task snapshot has been acknowledged and this is a redundant ack,
// just let it go!
return new Result(true);
}
} else {
int rst = clientContext.getStore().getTaskSnapshotDao().taskSnapshotAck(taskSnapshot);
if (rst
<= 0) { //indicates that this task snapshot has been acknowledged and this is a redundant ack,
// just let it go!
return new Result(true);
}
}
int status = taskSnapshot.getStatus();
Long jobInstanceId = taskSnapshot.getJobInstanceId();
ConcurrentHashMap> executionCounterMapByReceiveNode
= clientContext.getExecutionCounterTable().get(jobInstanceId);
if (executionCounterMapByReceiveNode == null) {
executionCounterMapByReceiveNode
= new ConcurrentHashMap>();
ConcurrentHashMap>
executionCounterMapByReceiveNodeExist = clientContext.getExecutionCounterTable().putIfAbsent(
jobInstanceId, executionCounterMapByReceiveNode);
if (executionCounterMapByReceiveNodeExist != null) {
executionCounterMapByReceiveNode = executionCounterMapByReceiveNodeExist;
}
}
String receiveNode = remoteMachine.getRemoteAddress().substring(0,
remoteMachine.getRemoteAddress().indexOf(':') + 1) + remoteMachine.getNodeListenPort();
ConcurrentHashMap executionCounterMapByTaskName = executionCounterMapByReceiveNode
.get(receiveNode);
if (executionCounterMapByTaskName == null) {
executionCounterMapByTaskName = new ConcurrentHashMap();
ConcurrentHashMap executionCounterMapByTaskNameExist
= executionCounterMapByReceiveNode.putIfAbsent(receiveNode, executionCounterMapByTaskName);
if (executionCounterMapByTaskNameExist != null) {
executionCounterMapByTaskName = executionCounterMapByTaskNameExist;
}
}
String taskName = taskSnapshot.getTaskName();
ExecutionCounter executionCounter = executionCounterMapByTaskName.get(taskName);
if (executionCounter == null) {
executionCounter = new ExecutionCounter();
executionCounter.setReceiveNode(receiveNode);
executionCounter.setTaskName(taskName);
ExecutionCounter executionCounterExist = executionCounterMapByTaskName.putIfAbsent(taskName,
executionCounter);
if (executionCounterExist != null) {
executionCounter = executionCounterExist;
}
}
// if (taskSnapshot.isCompensation()) { //补偿任务
// if (status == Constants.TASK_STATUS_SUCCESS) {
// executionCounter.getSuccessCounter().getAndIncrement();
//// executionCounter.getFailCounter().decrementAndGet();
// } else {
// executionCounter.getFailCounter().getAndIncrement();
// }
// } else {
if (status == Constants.TASK_STATUS_SUCCESS) {
executionCounter.getSuccessCounter().getAndIncrement();
executionCounter.getQueuedCounter().decrementAndGet();
} else {
executionCounter.getFailCounter().getAndIncrement();
executionCounter.getQueuedCounter().decrementAndGet();
}
// }
return new Result(true);
} catch (Throwable t) {
logger.error("Task snapshot ack failed, {}", taskSnapshot, t);
return new Result(false);
}
}
public boolean stopTask(long jobId, long jobInstanceId) {
try {
// clientContext.getGridTaskSender().addInterruptedJobInstance(jobInstanceId);
clientContext.getGridJobManager().addInterruptedJobInstance(jobInstanceId);
// ExecutorService executorService = executorServiceMap.get(jobInstanceId);
// if (executorService != null) {
// executorServiceMap.remove(jobInstanceId);
// executorService.shutdown();
// }
clientContext.getGridTaskSender().clearInsertBuffer(jobInstanceId);
clientContext.getExecutor().doGridJobCleanTaskForStop(jobInstanceId);
//clientContext.getGridTaskSender().addInterruptedJobInstance(jobInstanceId);
fixDispatchedTasksStatus(jobInstanceId);
return true;
} catch (Throwable throwable) {
logger.error("failed to stop job, id = {}, jonInstanceId = {}", jobId, jobInstanceId, throwable);
return false;
}
}
/**
* set status of tasks whose status is not success to fail and retry count as zero
*
* jobInstanceId
*/
private void fixDispatchedTasksStatus(final long jobInstanceId) throws AccessException {
//TODO update execution counter
// ExecutionCounter executionCounter = clientContext.getExecutionCounterMap().get(jobInstanceId);
// executionCounter.getFailCounter().set(executionCounter.getTotalCounter().get() - executionCounter
// .getSuccessCounter().get());
// executionCounter.getQueuedCounter().set(0);
//TODO detete all tasks associated with the specified job instance id
new Thread(new Runnable() {
@Override
public void run() {
boolean stopFlag = false;
while (!stopFlag) {
try {
TimeUnit.SECONDS.sleep(10);
long count = clientContext.getStore().getTaskSnapshotDao().deleteByJobInstanceId(jobInstanceId);
while (count > 0) {
count = clientContext.getStore().getTaskSnapshotDao().deleteByJobInstanceId(jobInstanceId);
}
stopFlag = true;
} catch (Throwable e) {
logger.error("deleteByJobInstanceId error", e);
stopFlag = false;
}
}
}
}).start();
//
}
public ConcurrentHashMap getExecutorServiceMap() {
return executorServiceMap;
}
}