Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.dts.client.executor.grid.GridTaskSender Maven / Gradle / Ivy
package com.alibaba.dts.client.executor.grid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import com.alibaba.dts.client.executor.grid.flowcontrol.FlowControlParameterWatcher;
import com.alibaba.dts.client.executor.grid.queue.TaskEvent;
import com.alibaba.dts.client.executor.grid.queue.send.SendManager;
import com.alibaba.dts.client.executor.grid.unit.FlexibleThreadPoolExecutor;
import com.alibaba.dts.client.executor.job.context.ClientContextImpl;
import com.alibaba.dts.client.executor.job.context.JobContext;
import com.alibaba.dts.common.constants.Constants;
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.TaskSnapshot;
import com.alibaba.dts.common.exception.AccessException;
import com.alibaba.dts.common.exception.InitException;
import com.alibaba.dts.common.logger.SchedulerXLoggerFactory;
import com.alibaba.dts.common.logger.innerlog.Logger;
import com.alibaba.dts.common.util.BytesUtil;
import com.alibaba.dts.common.util.BytesUtil4Client;
import com.alibaba.dts.common.util.NamedThreadFactory;
/**
* @author Ronan Zhan
* @date 2016/12/14.
*/
public class GridTaskSender {
private static final Logger logger = SchedulerXLoggerFactory.getLogger(GridTaskSender.class);
private SendManager sendManager = new SendManager();
private long maxBodySize;
private long flowControlCountGate = 500 * 1000;
private final ClientContextImpl clientContext;
private ConcurrentHashMap>> tasksForInsertBufferMap
= new ConcurrentHashMap>>();
private ConcurrentHashMap tasksForInsertBufferMapFlag = new ConcurrentHashMap();
private ExecutorService reSendExecutorService = new FlexibleThreadPoolExecutor(8, 16, 60, TimeUnit.SECONDS, new LinkedBlockingDeque(), new NamedThreadFactory("SchedulerX-Tasks-ReSend-Thread-"));
public GridTaskSender(ClientContextImpl clientContext) {
this.clientContext = clientContext;
}
private void initSchedulerXSendQueue() throws InitException {
if (clientContext == null) {
logger.equals("[GridTaskSender] clientContext is null!");
throw new InitException("[GridTaskSender] clientContext is null!");
}
sendManager.init(clientContext);
//sendManager.setTaskMergeHandler(taskMergeHandler);
//sendManager.initialProcessChain(this.clientContext);
//sendManager.startWork();
}
public void init() throws InitException {
try {
maxBodySize = clientContext.getClientConfig().getMaxBodySize();
initSchedulerXSendQueue();
initTasksForInsertBufferConsumer();
logger.info("[GridTaskSender]: init over");
} catch (Throwable e) {
logger.error("[GridTaskSender]: init error:", e);
}
}
private void initTasksForInsertBufferConsumer() throws InitException {
new TaskForInsertConsumer().init();
}
public Result dispatchTaskList(List extends Object> taskList, String taskName, JobContext jobContext,
int dispatchMode) {
long jobId = jobContext.getJob().getId();
long jobInstanceId = jobContext.getJobInstanceSnapshot().getId();
logger.info("{} tasks dispatched, jobId={}, jobInstanceId={}", taskList.size(), jobId, jobInstanceId);
if (clientContext.getGridJobManager().containsInterruptedJobInstance(
jobContext.getJobInstanceSnapshot().getId())) {
logger.warn("[GridTaskSender]: dispatchTaskList is interrupted forcedly:"
+ ",jobId=" + jobId
+ ",jobInstanceId=" + jobInstanceId
+ ",total tasks=" + taskList.size());
return new Result(false);
}
boolean result = true;
List taskEvents = new ArrayList();
try {
List nodes = null;
int retryCount = 10;
while (retryCount > 0) {
nodes = clientContext.getNodeRemoting().getNodes(clientContext.getClientConfig().getGroupId(), jobId, jobContext.getJob().getType());
if (nodes == null || nodes.isEmpty()) {
logger.warn("there is no working nodes existed, groupId={}, jobId={}, so it will retry {} times", clientContext.getClientConfig().getGroupId(), jobId, retryCount);
if (--retryCount <= 0) {
throw new RuntimeException("there is no working nodes existed, groupId={}, jobId={}, and it has retried for 10 times");
}
TimeUnit.SECONDS.sleep(10);
continue;
} else {
break;
}
}
sendManager.resetRoutesMachines(jobContext.getJob().getId(), nodes);
int position = 0;
long successProcess = 0;
long totalStart = System.currentTimeMillis();
int batchSize = 3000;
//if (dispatchMode == 1) { batchSize = calculateBatchSize(taskList, nodes); }
while (position < taskList.size()) {
if (isInterruptedInstance(jobContext.getJobInstanceSnapshot().getId())) {
logger.warn("[GridTaskSender]: dispatchTaskList is interrupted forcedly:"
+ ",jobId:" + jobContext.getJob().getId()
+ ",jobInstanceId:" + jobContext.getJobInstanceSnapshot().getId()
+ ",total tasks:" + taskList.size()
+ ",put schedulerXSendQueue tasks:" + successProcess);
Result resultIntercept = new Result(false);
resultIntercept.setResultCode(ResultCode.TASK_SEND_INTERRUPT);
return resultIntercept;
}
ExecutableTask executableTask = null;
long start = System.currentTimeMillis();
if (dispatchMode == 1) {
executableTask = new ExecutableTask(jobContext.getJob(), jobContext.getJobInstanceSnapshot());
fillTaskSnapshot(executableTask, taskList.get(position), taskName);
TaskEvent taskEvent = new TaskEvent();
taskEvent.setExecutableTask(executableTask);
taskEvent.setTask(taskList.get(position));
if ((position + 1) % batchSize == 0) {
taskEvents.add(taskEvent);
//FlowControlStrategy flowControlStrategy = clientContext.getNodeConfig()
// .getFlowControlStrategy();
//if (flowControlStrategy == FlowControlStrategy.H2_COUNT_MULTI
// && FlowControlParameterWatcher.dbTasksCount.get() > flowControlCountGate) {//流控
// List taskEventTemp = new ArrayList(taskEvents);
// BlockingQueue> tasksForInsertBuffer = tasksForInsertBufferMap.get(
// jobContext.getJobInstanceSnapshot().getId());
// if (tasksForInsertBuffer == null) {
// tasksForInsertBuffer = new ArrayBlockingQueue>(512 * 1024);
// BlockingQueue> tasksForInsertBufferExsit = tasksForInsertBufferMap
// .putIfAbsent(jobContext.getJobInstanceSnapshot().getId(), tasksForInsertBuffer);
// if (tasksForInsertBufferExsit != null) {
// tasksForInsertBuffer = tasksForInsertBufferExsit;
// }
// }
// tasksForInsertBuffer.put(taskEventTemp);
//} else {
clientContext.getFlowControlChain().control(jobContext);
persistTasks(taskEvents, jobInstanceId);
sendManager.putTasksToRouteQueue(taskEvents, jobInstanceId);
long end = System.currentTimeMillis();
logger.debug(
"[GridTaskSender]: dispatchTaskList,executableTask has been put to schedulerXSendQueue, "
+ "jobId={}, jobInstanceId={}, taskName={}, consumptionTime={}, size={}",
executableTask.getJob().getId(), executableTask.getJobInstanceSnapshot().getId(), taskName,
(end - start), taskEvents.size());
//}
taskEvents.clear();
} else {
taskEvents.add(taskEvent);
}
successProcess++;
} else if (dispatchMode == 2) {
TaskSnapshot taskSnapshot = (TaskSnapshot) taskList.get(position);
executableTask = new ExecutableTask(jobContext.getJob(), jobContext.getJobInstanceSnapshot());
executableTask.setTaskSnapshot(taskSnapshot);
executableTask.getTaskSnapshot().setReSent(true);
executableTask.setCompensation(true);
TaskEvent taskEvent = new TaskEvent();
taskEvent.setExecutableTask(executableTask);
taskEvent.setTask(getTaskObject(taskSnapshot));
sendManager.putSingleTaskToRouteQueue(taskEvent);
successProcess++;
} else if (dispatchMode == 3) {
TaskSnapshot taskSnapshot = (TaskSnapshot) taskList.get(position);
executableTask = new ExecutableTask(jobContext.getJob(), jobContext.getJobInstanceSnapshot());
executableTask.setTaskSnapshot(taskSnapshot);
TaskEvent taskEvent = new TaskEvent();
taskEvent.setExecutableTask(executableTask);
taskEvent.setTask(getTaskObject(taskSnapshot));
sendManager.putSingleTaskToRouteQueue(taskEvent);
successProcess++;
}
position = position + 1;
}
if (dispatchMode == 1) {
if (taskEvents.size() > 0) {
clientContext.getFlowControlChain().control(jobContext);
persistTasks(taskEvents, jobInstanceId);
sendManager.putTasksToRouteQueue(taskEvents, jobInstanceId);
taskEvents.clear();
}
}
long totalEnd = System.currentTimeMillis();
logger.debug(
"[GridTaskSender]: dispatchTaskList,executableTask has been put to schedulerXSendQueue, jobId={}, "
+ "jobInstanceId={}, total={}, put schedulerXSendQueue tasks={}, taskName={}, consumptionTime={}",
jobContext.getJob().getId(), jobContext.getJobInstanceSnapshot().getId(), taskList.size(),
successProcess, taskName, (totalEnd - totalStart));
} catch (Throwable e) {
result = false;
logger.error("[GridTaskSender]: dispatchTaskList error,", e);
}
return new Result(result);
}
// calculate batch size by nodes size, 2 multiplied is for reason the result we can make dispatch more dispersive
private int calculateBatchSize(List extends Object> taskList, List nodes) {
int batchSize = clientContext.getNodeConfig().getTaskInsertBatchSize();
if (batchSize == 0) {
if (taskList.size() < nodes.size() * 2) {
batchSize = 1;
} else {
batchSize = taskList.size() / (nodes.size() * 2);
}
if (batchSize > 3000) {
batchSize = 3000;
}
return batchSize;
}
return batchSize;
}
public Result dispatchTaskList(List extends Object> taskList, String taskName, JobContext jobContext) {
return dispatchTaskList(taskList, taskName, jobContext, 1);
}
public Result dispatchCompensateTaskList(List taskList, JobContext jobContext) {
return dispatchTaskList(taskList, null, jobContext, 2);
}
public Result dispatchRetryTaskList(List taskList, JobContext jobContext) {
return dispatchTaskList(taskList, null, jobContext, 3);
}
class TaskForInsertConsumer {
private ExecutorService bossThreadPool = Executors.newSingleThreadExecutor(
new NamedThreadFactory("SchedulerX-TaskForInsertConsumer-Boss-"));
private ExecutorService workerThreadPool = Executors.newFixedThreadPool(16,
new NamedThreadFactory("SchedulerX-TaskForInsertConsumer-Worker-"));
public void init() throws InitException {
try {
bossThreadPool.submit(new Runnable() {
@Override
public void run() {
while (true) {
try {
for (Map.Entry>> entry : tasksForInsertBufferMap
.entrySet()) {
final Long jobInstanceId = entry.getKey();
final BlockingQueue> queue = entry.getValue();
if (tasksForInsertBufferMapFlag.containsKey(jobInstanceId)) {
continue;
}
tasksForInsertBufferMapFlag.put(jobInstanceId, true);
workerThreadPool.submit(new Runnable() {
@Override
public void run() {
while (tasksForInsertBufferMap.containsKey(jobInstanceId)) {
try {
final List taskEvents = queue.poll(10, TimeUnit.SECONDS);
if (taskEvents == null || taskEvents.size() <= 0) {
continue;
}
while (true) {
if (FlowControlParameterWatcher.dbTasksCount.get()
< flowControlCountGate) {
TaskEvent taskEvent = taskEvents.get(0);
persistTasks(taskEvents, jobInstanceId);
sendManager.putTasksToRouteQueue(taskEvents, jobInstanceId);
logger.debug(
"[TaskForInsertConsumer]: dispatchTaskList, "
+ "executableTask has been put to "
+ "schedulerXSendQueue, jobId={}, "
+ "jobInstanceId={}, size={}",
taskEvent.getExecutableTask().getJob().getId(),
taskEvent.getExecutableTask().getJobInstanceSnapshot()
.getId(), taskEvents.size());
break;
} else {
TimeUnit.SECONDS.sleep(5);
}
}
} catch (Throwable throwable) {
logger.error("TaskForInsertConsumer error", throwable);
}
}
}
});
}
TimeUnit.SECONDS.sleep(1);
} catch (Throwable throwable) {
logger.error("TaskForInsertConsumer error", throwable);
}
}
}
});
} catch (
Throwable throwable)
{
throw new InitException(throwable);
}
}
}
private void fillTaskSnapshot(ExecutableTask executableTask, Object task, String taskName) {
byte[] body = null;
try {
body = BytesUtil4Client.objectToBytes(task);
} catch (Throwable e) {
logger.error("[GridTaskSender]: fillTaskSnapshot objectToBytes error"
+ ", taskName:" + taskName
+ ", task:" + task, e);
}
if (BytesUtil4Client.isEmpty(body)) {
logger.error("[GridTaskSender]: fillTaskSnapshot objectToBytes body is empty"
+ ", taskName:" + taskName
+ ", task:" + task);
return;
}
if (body.length > maxBodySize) {
throw new RuntimeException("[GridTaskSender]: single task is too large, more than 64KB");
}
TaskSnapshot taskSnapshot = new TaskSnapshot();
taskSnapshot.setGmtCreate(new Date());
taskSnapshot.setGmtModified(new Date());
taskSnapshot.setJobInstanceId(executableTask.getJobInstanceSnapshot().getId());
taskSnapshot.setJobProcessor(executableTask.getJob().getJobProcessor());
taskSnapshot.setBody(body);
taskSnapshot.setStatus(Constants.TASK_STATUS_INIT);
taskSnapshot.setTaskName(taskName);
taskSnapshot.setRetryCount(0);
executableTask.setTaskSnapshot(taskSnapshot);
}
protected Object getTaskObject(TaskSnapshot taskSnapshot) {
Object resultTask = null;
if (Constants.DEFAULT_ROOT_LEVEL_TASK_NAME.equals(taskSnapshot.getTaskName())) {
if (BytesUtil.isEmpty(taskSnapshot.getBody())) {
logger.error("[GridTaskSender]: BytesUtil setTask bytesToObject error, body is empty"
+ ", instanceId:" + taskSnapshot.getJobInstanceId()
+ ", id:" + taskSnapshot.getId());
return null;
}
try {
resultTask = BytesUtil.bytesToObject(taskSnapshot.getBody());
} catch (Throwable e) {
logger.error("[GridTaskSender]: BytesUtil setTask bytesToObject error"
+ ", instanceId:" + taskSnapshot.getJobInstanceId()
+ ", id:" + taskSnapshot.getId(), e);
}
} else {
if (BytesUtil4Client.isEmpty(taskSnapshot.getBody())) {
logger.error("[GridTaskSender]: BytesUtil4Client setTask bytesToObject error, body is empty"
+ ", instanceId:" + taskSnapshot.getJobInstanceId()
+ ", id:" + taskSnapshot.getId());
return null;
}
try {
resultTask = BytesUtil4Client.bytesToObject(taskSnapshot.getBody());
} catch (Throwable e) {
logger.error("[GridTaskSender]: BytesUtil4Client setTask bytesToObject error"
+ ", instanceId:" + taskSnapshot.getJobInstanceId()
+ ", id:" + taskSnapshot.getId(), e);
}
}
return resultTask;
}
private void persistTasks(List taskEvents, long jobInstanceId) {
if (taskEvents.isEmpty()) {
return;
}
List taskSnapshots = new ArrayList();
if (clientContext.getGridJobManager().containsInterruptedJobInstance(jobInstanceId)) {
return;
}
for (TaskEvent taskEvent : taskEvents) {
TaskSnapshot taskSnapshot = taskEvent.getExecutableTask().getTaskSnapshot();
taskSnapshot.setId(clientContext.getIdWorker().nextId());
taskSnapshots.add(taskSnapshot);
}
try {
clientContext.getStore().getTaskSnapshotDao().insertBatch(taskSnapshots);
} catch (AccessException e) {
logger.error("failed to insert tasksnapshots batch. jobInstanceId=" + jobInstanceId, e);
}
}
public void addInterruptedJobInstance(long instanceId) {
try {
clientContext.getGridJobManager().addInterruptedJobInstance(instanceId);
logger.info("[GridTaskSender]: addInterceptInstance instanceId:" + instanceId);
} catch (Throwable e) {
logger.error("[GridTaskSender]: addInterceptInstance error,instanceId:" + instanceId, e);
}
}
public void removeInterruptedJobInstance(long instanceId) {
try {
clientContext.getGridJobManager().removeInterruptedJobInstance(instanceId);
logger.info("[GridTaskSender]: removeInterceptInstance instanceId:" + instanceId);
} catch (Throwable e) {
logger.error("[GridTaskSender]: removeInterceptInstance error,instanceId:" + instanceId, e);
}
}
public boolean isInterruptedInstance(long instanceId) {
if (clientContext.getGridJobManager().containsInterruptedJobInstance(instanceId)) {
return true;
}
return false;
}
public ExecutorService getReSendExecutorService() {
return reSendExecutorService;
}
public ConcurrentHashMap>> getTasksForInsertBufferMap() {
return tasksForInsertBufferMap;
}
public void clearInsertBuffer(long jobInstanceId) {
tasksForInsertBufferMap.remove(jobInstanceId);
tasksForInsertBufferMapFlag.remove(jobInstanceId);
}
public SendManager getSendManager() {
return sendManager;
}
}