介绍
PeerEurekaNode 类处理所有的更新请求。如
Register,Renew,Cancel,Expiration and Status Changes 等。本文以register为例。介绍底层任务请求的框架。
PeerEurekaNode register请求
入口都是 通过 batchingDispatcher分发任务
public void register(final InstanceInfo info) throws Exception {
long expiryTime = System.currentTimeMillis() + getLeaseRenewalOf(info);
batchingDispatcher.process(
taskId("register", info),
new InstanceReplicationTask(targetHost, Action.Register, info, null, true) {
public EurekaHttpResponse<Void> execute() {
return replicationClient.register(info);
}
},
expiryTime
);
}
2. 总体流程图
源码分析1 AcceptorExecutor
/**
* An active object with an internal thread accepting tasks from clients, and dispatching them to
* workers in a pull based manner. Workers explicitly request an item or a batch of items whenever they are
* available. This guarantees that data to be processed are always up to date, and no stale data processing is done.
*
* no stale data :过时的数据
*
* <h3>Task identification</h3>
* Each task passed for processing has a corresponding task id. This id is used to remove duplicates (replace
* older copies with newer ones).
*
* 每个任务都有一个唯一的任务Id.这个id被用来移除重复或者替换较老任务。
*
* <h3>Re-processing</h3>
* If data processing by a worker failed, and the failure is transient in nature, the worker will put back the
* task(s) back to the {@link AcceptorExecutor}. This data will be merged with current workload, possibly discarded if
* a newer version has been already received.
*
* 重试处理:
* 如果在工作者线程中执行失败。并且这个失败是临时的。那么工作者线程将分发这个任务给AcceptorExecutor。
* 这个任务将根AcceptorExecutor中的任务进行merge。可能被丢弃如果有一个更新版本的任务已经被接收。
* @author Tomasz Bak
*/
class AcceptorExecutor<ID, T> {
private static final Logger logger = LoggerFactory.getLogger(AcceptorExecutor.class);
/**最大缓冲大小*/
private final int maxBufferSize;
/**最大批处理任务个数*/
private final int maxBatchingSize;
/**最大批处理延迟*/
private final long maxBatchingDelay;
private final AtomicBoolean isShutdown = new AtomicBoolean(false);
/**存放接收到任务的队列*/
private final BlockingQueue<TaskHolder<ID, T>> acceptorQueue = new LinkedBlockingQueue<>();
/**再次处理队列*/
private final BlockingDeque<TaskHolder<ID, T>> reprocessQueue = new LinkedBlockingDeque<>();
/**使用单线程处理任务*/
private final Thread acceptorThread;
/**阻塞任务map*/
private final Map<ID, TaskHolder<ID, T>> pendingTasks = new HashMap<>();
/**处理任务的顺序队列。头部存放最近提交的任务*/
private final Deque<ID> processingOrder = new LinkedList<>();
/**
* Semaphore经常用于限制获取某种资源的线程数量
* Semaphore是计数信号量。Semaphore管理一系列许可证。
* 每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;
* 每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法
*
* 下面举个例子,比如说操场上有5个跑道,
* 一个跑道一次只能有一个学生在上面跑步,
* 一旦所有跑道在使用,那么后面的学生就需要等待,直到有一个学生不跑了
*/
private final Semaphore singleItemWorkRequests = new Semaphore(0);
private final BlockingQueue<TaskHolder<ID, T>> singleItemWorkQueue = new LinkedBlockingQueue<>();
private final Semaphore batchWorkRequests = new Semaphore(0);
private final BlockingQueue<List<TaskHolder<ID, T>>> batchWorkQueue = new LinkedBlockingQueue<>();
/**流量整形类*/
private final TrafficShaper trafficShaper;
AcceptorExecutor(String id,
int maxBufferSize,
int maxBatchingSize,
long maxBatchingDelay,
long congestionRetryDelayMs,
long networkFailureRetryMs) {
this.maxBufferSize = maxBufferSize;
this.maxBatchingSize = maxBatchingSize;
this.maxBatchingDelay = maxBatchingDelay;
/**
* @congestionRetryDelayMs 故障发生后延迟多少秒进行重试
* @networkFailureRetryMs 网络失败后重试的时间
*/
this.trafficShaper = new TrafficShaper(congestionRetryDelayMs, networkFailureRetryMs);
ThreadGroup threadGroup = new ThreadGroup("eurekaTaskExecutors");
/***
* 单一线程执行任务
*/
this.acceptorThread = new Thread(threadGroup, new AcceptorRunner(), "TaskAcceptor-" + id);
/**
* java中线程分为两种类型:用户线程和守护线程。
* 通过Thread.setDaemon(false)设置为用户线程;
* 通过Thread.setDaemon(true)设置为守护线程。如果不设置次属性,
* 默认为用户线程。
*
* 用户线程和守护线程的区别:
1. 主线程结束后用户线程还会继续运行,JVM存活;主线程结束后守护线程和JVM的状态又下面第2条确定。
2.如果没有用户线程,都是守护线程,那么JVM结束(随之而来的是所有的一切烟消云散,包括所有的守护线程)。
*/
this.acceptorThread.setDaemon(true);
this.acceptorThread.start();
}
void process(ID id, T task, long expiryTime) {
acceptorQueue.add(new TaskHolder<ID, T>(id, task, expiryTime));
acceptedTasks++;
}
/**
* 失败重试任务
* @param holders
* @param processingResult
*/
void reprocess(List<TaskHolder<ID, T>> holders, ProcessingResult processingResult) {
reprocessQueue.addAll(holders);
/**
* 需要重复执行的任务数
*/
replayedTasks += holders.size();
trafficShaper.registerFailure(processingResult);
}
/**
* 失败重试任务
* @param taskHolder
* @param processingResult
*/
void reprocess(TaskHolder<ID, T> taskHolder, ProcessingResult processingResult) {
/**添加任务到队列尾部。如果没有多余的空间。则抛出异常*/
reprocessQueue.add(taskHolder);
replayedTasks++;
trafficShaper.registerFailure(processingResult);
}
BlockingQueue<TaskHolder<ID, T>> requestWorkItem() {
/**
* 增加一个许可证
*/
singleItemWorkRequests.release();
return singleItemWorkQueue;
}
BlockingQueue<List<TaskHolder<ID, T>>> requestWorkItems() {
/***
* 添加一个许可证
*/
batchWorkRequests.release();
return batchWorkQueue;
}
void shutdown() {
if (isShutdown.compareAndSet(false, true)) {
acceptorThread.interrupt();
}
}
/**
* acceptor线程实现
*/
class AcceptorRunner implements Runnable {
@Override
public void run() {
long scheduleTime = 0;
while (!isShutdown.get()) {
try {
/**
* 把acceptorQueue及reprocessQueue队列中的项
* 到缓存及任务队列中
*/
drainInputQueues();
/**
* 任务队列中的任务总数
*/
int totalItems = processingOrder.size();
long now = System.currentTimeMillis();
if (scheduleTime < now) {
scheduleTime = now + trafficShaper.transmissionDelay();
}
if (scheduleTime <= now) {
/**
* 把processingOrder队列中的任务 转到 workQueue中
*
*/
assignBatchWork();
assignSingleItemWork();
}
// If no worker is requesting data or there is a delay injected by the traffic shaper,
// sleep for some time to avoid tight loop.
/**
* 如果没有进入 到scheduleTime <= now 此代码块
* 说明了 工作者线程没有请求数据 或者都是重试的请求被流量整形进行延迟了
* 让线程sleep(10)。避免密集的循环
*/
if (totalItems == processingOrder.size()) {
Thread.sleep(10);
}
} catch (InterruptedException ex) {
// Ignore
} catch (Throwable e) {
// Safe-guard, so we never exit this loop in an uncontrolled way.
logger.warn("Discovery AcceptorThread error", e);
}
}
}
/**
* 判断缓存是否超过最大大小
* @return
*/
private boolean isFull() {
return pendingTasks.size() >= maxBufferSize;
}
/**
* 把acceptorQueue及reprocessQueue队列中的项
* 到缓存及任务队列中
* @throws InterruptedException
*/
private void drainInputQueues() throws InterruptedException {
do {
/**
* 把reprocess队列中的元素转移到pendingTasks 和processingOrder 队列中
*/
drainReprocessQueue();
drainAcceptorQueue();
if (!isShutdown.get()) {
// If all queues are empty, block for a while on the acceptor queue
/**
* 如果reprocessQueue.isEmpty() && acceptorQueue.isEmpty() && pendingTasks.isEmpty()
* 则调用acceptorQueue.poll()等待10毫秒。具有超时机制
*/
if (reprocessQueue.isEmpty() && acceptorQueue.isEmpty() && pendingTasks.isEmpty()) {
TaskHolder<ID, T> taskHolder = acceptorQueue.poll(10, TimeUnit.MILLISECONDS);
if (taskHolder != null) {
appendTaskHolder(taskHolder);
}
}
}
} while (!reprocessQueue.isEmpty() || !acceptorQueue.isEmpty() || pendingTasks.isEmpty());
}
/**
* 把acceptor队列中的内容 存放到
* 缓存及任务队列中
*/
private void drainAcceptorQueue() {
while (!acceptorQueue.isEmpty()) {
appendTaskHolder(acceptorQueue.poll());
}
}
/**
* 把reprocessQueue队列中的请求
* 存放到缓存及任务队列中
*/
private void drainReprocessQueue() {
long now = System.currentTimeMillis();
while (!reprocessQueue.isEmpty() && !isFull()) {
TaskHolder<ID, T> taskHolder = reprocessQueue.pollLast();
ID id = taskHolder.getId();
/**
* 如果任务的终止日期 < 当前日期
* 则标记此任务为过期任务
*/
if (taskHolder.getExpiryTime() <= now) {
expiredTasks++;
}
/**
* 如果阻塞任务里包含此任务id。则任务是重复提交任务。不作处理
*/
else if (pendingTasks.containsKey(id)) {
overriddenTasks++;
} else {
/**存放任务到等待任务map中*/
pendingTasks.put(id, taskHolder);
/**头部存放最近提交的任务*/
processingOrder.addFirst(id);
}
}
/**
* 如果缓存是满的。则直接丢弃、监控记录做相关记录
*/
if (isFull()) {
queueOverflows += reprocessQueue.size();
reprocessQueue.clear();
}
}
/**
* 添加任务到缓存和任务队列中
* @param taskHolder
*/
private void appendTaskHolder(TaskHolder<ID, T> taskHolder) {
if (isFull()) {
/***
* 如果缓存的最大队列 满了。则丢弃。则拒绝服务。丢弃最近提交的
*
* poll():移除头部元素。如果队列为空。则返回null
*/
pendingTasks.remove(processingOrder.poll());
queueOverflows++;
}
/**
* map put() 如果以前存在此key的值。则返回旧值。否则返回null
*/
TaskHolder<ID, T> previousTask = pendingTasks.put(taskHolder.getId(), taskHolder);
if (previousTask == null) {
processingOrder.add(taskHolder.getId());
} else {
overriddenTasks++;
}
}
/**
* 构造单词请求数据
* 一次只能提交一个任务
*/
void assignSingleItemWork() {
if (!processingOrder.isEmpty()) {
/**
* 获得进入许可。如果获得一个许可。则返回true
* 否则。直接返回false
*/
if (singleItemWorkRequests.tryAcquire(1)) {
long now = System.currentTimeMillis();
while (!processingOrder.isEmpty()) {
/**
* 取出队列头部的元素 或者没有返回Null
* */
ID id = processingOrder.poll();
/*
从缓存中移除任务
*/
TaskHolder<ID, T> holder = pendingTasks.remove(id);
/**
* 判断任务是否过期
*/
if (holder.getExpiryTime() > now) {
singleItemWorkQueue.add(holder);
return;
}
expiredTasks++;
}
/**
* 归还许可值
*/
singleItemWorkRequests.release();
}
}
}
/**
* 把processingOrder队列中的任务 存放到请求队列中
* 给批量请求进行复制
* 存放到批量请求队列中农
*/
void assignBatchWork() {
/**
* hasEnoughTasksForNextBatch
* 判断是否满足批量任务处理
*/
if (hasEnoughTasksForNextBatch()) {
/**
* 获得进入许可
*/
if (batchWorkRequests.tryAcquire(1)) {
long now = System.currentTimeMillis();
/**限定一次批任务中 最大的提交数*/
int len = Math.min(maxBatchingSize, processingOrder.size());
List<TaskHolder<ID, T>> holders = new ArrayList<>(len);
while (holders.size() < len && !processingOrder.isEmpty()) {
ID id = processingOrder.poll();
/**
* 从缓存中移除数据
*/
TaskHolder<ID, T> holder = pendingTasks.remove(id);
if (holder.getExpiryTime() > now) {
holders.add(holder);
} else {
expiredTasks++;
}
}
if (holders.isEmpty()) {
/**
* 释放许可
*/
batchWorkRequests.release();
} else {
batchSizeMetric.record(holders.size(), TimeUnit.MILLISECONDS);
batchWorkQueue.add(holders);
}
}
}
}
/**
* 判断是否有足够的任务为下一次批处理任务
* @return
*/
private boolean hasEnoughTasksForNextBatch() {
/**
* 正在处理的任务队列 为空
* 则return false
*/
if (processingOrder.isEmpty()) {
return false;
}
/**
* 如果阻塞的任务大小 > 最大缓存大小
* return true
*/
if (pendingTasks.size() >= maxBufferSize) {
return true;
}
TaskHolder<ID, T> nextHolder = pendingTasks.get(processingOrder.peek());
long delay = System.currentTimeMillis() - nextHolder.getSubmitTimestamp();
return delay >= maxBatchingDelay;
}
}
}
源码分析2 TaskExecutors
/**
* {@link TaskExecutors} instance holds a number of worker threads that cooperate with {@link AcceptorExecutor}.
* Each worker sends a job request to {@link AcceptorExecutor} whenever it is available, and processes it once
* provided with a task(s).
*
* 这个类保存了线程集合类同 AcceptorExecutor交互
* 当AcceptorExecutor可用时。工作者线程发送一个Job请求到AcceptorExecutor
* @author Tomasz Bak
*/
class TaskExecutors<ID, T> {
private static final Logger logger = LoggerFactory.getLogger(TaskExecutors.class);
private final AtomicBoolean isShutdown;
private final List<Thread> workerThreads;
TaskExecutors(WorkerRunnableFactory<ID, T> workerRunnableFactory, int workerCount, AtomicBoolean isShutdown) {
this.isShutdown = isShutdown;
this.workerThreads = new ArrayList<>();
ThreadGroup threadGroup = new ThreadGroup("eurekaTaskExecutors");
for (int i = 0; i < workerCount; i++) {
WorkerRunnable<ID, T> runnable = workerRunnableFactory.create(i);
Thread workerThread = new Thread(threadGroup, runnable, runnable.getWorkerName());
workerThreads.add(workerThread);
workerThread.setDaemon(true);
workerThread.start();
}
}
/**
* 线程关闭方法
*/
void shutdown() {
if (isShutdown.compareAndSet(false, true)) {
for (Thread workerThread : workerThreads) {
workerThread.interrupt();
}
}
}
/**
* 创建提交单一任务的executor
* @param name
* @param workerCount
* @param processor 开始执行真正的任务请求
* @param acceptorExecutor
* @param <ID>
* @param <T>
* @return
*/
static <ID, T> TaskExecutors<ID, T> singleItemExecutors(final String name,
int workerCount,
final TaskProcessor<T> processor,
final AcceptorExecutor<ID, T> acceptorExecutor) {
final AtomicBoolean isShutdown = new AtomicBoolean();
final TaskExecutorMetrics metrics = new TaskExecutorMetrics(name);
return new TaskExecutors<>(new WorkerRunnableFactory<ID, T>() {
@Override
public WorkerRunnable<ID, T> create(int idx) {
return new SingleTaskWorkerRunnable<>("TaskNonBatchingWorker-" + name + '-' + idx, isShutdown, metrics, processor, acceptorExecutor);
}
}, workerCount, isShutdown);
}
static <ID, T> TaskExecutors<ID, T> batchExecutors(final String name,
int workerCount,
final TaskProcessor<T> processor,
final AcceptorExecutor<ID, T> acceptorExecutor) {
final AtomicBoolean isShutdown = new AtomicBoolean();
return new TaskExecutors<>(new WorkerRunnableFactory<ID, T>() {
@Override
public WorkerRunnable<ID, T> create(int idx) {
return new BatchWorkerRunnable<>("TaskBatchingWorker-" +name + '-' + idx, isShutdown, metrics, processor, acceptorExecutor);
}
}, workerCount, isShutdown);
}
void registerTaskResult(ProcessingResult result, int count) {
switch (result) {
case Success:
numberOfSuccessfulExecutions += count;
break;
//临时错误
case TransientError:
numberOfTransientError += count;
break;
//永久错误
case PermanentError:
numberOfPermanentError += count;
break;
}
}
<ID, T> void registerExpiryTime(TaskHolder<ID, T> holder) {
taskWaitingTimeForProcessing.record(System.currentTimeMillis() - holder.getSubmitTimestamp(), TimeUnit.MILLISECONDS);
}
<ID, T> void registerExpiryTimes(List<TaskHolder<ID, T>> holders) {
long now = System.currentTimeMillis();
for (TaskHolder<ID, T> holder : holders) {
taskWaitingTimeForProcessing.record(now - holder.getSubmitTimestamp(), TimeUnit.MILLISECONDS);
}
}
}
interface WorkerRunnableFactory<ID, T> {
WorkerRunnable<ID, T> create(int idx);
}
/**
* WorkerRunnable 基类
* @param <ID>
* @param <T>
*/
abstract static class WorkerRunnable<ID, T> implements Runnable {
final String workerName;
final AtomicBoolean isShutdown;
final TaskExecutorMetrics metrics;
final TaskProcessor<T> processor;
/**
* acceptor线程执行器
* 充当任务分发。把任务队列交给 taskExecutor执行者
* */
final AcceptorExecutor<ID, T> taskDispatcher;
WorkerRunnable(String workerName,
AtomicBoolean isShutdown,
TaskExecutorMetrics metrics,
TaskProcessor<T> processor,
AcceptorExecutor<ID, T> taskDispatcher) {
this.workerName = workerName;
this.isShutdown = isShutdown;
this.metrics = metrics;
this.processor = processor;
this.taskDispatcher = taskDispatcher;
}
String getWorkerName() {
return workerName;
}
}
/**
* 一次提交多个任务的runnable
* @param <ID>
* @param <T>
*/
static class BatchWorkerRunnable<ID, T> extends WorkerRunnable<ID, T> {
BatchWorkerRunnable(String workerName,
AtomicBoolean isShutdown,
TaskExecutorMetrics metrics,
TaskProcessor<T> processor,
AcceptorExecutor<ID, T> acceptorExecutor) {
super(workerName, isShutdown, metrics, processor, acceptorExecutor);
}
@Override
public void run() {
try {
while (!isShutdown.get()) {
/**
* 从acceptor线程中获得请求任务集合
*/
List<TaskHolder<ID, T>> holders = getWork();
metrics.registerExpiryTimes(holders);
/**
* 转变到List<T></>
*/
List<T> tasks = getTasksOf(holders);
/**批量任务进行处理*/
ProcessingResult result = processor.process(tasks);
switch (result) {
case Success:
break;
case Congestion:
case TransientError:
/**
* 如果集合中的任何一个任务发生Congestion或者TransientError
* 则整个集合进行重试
*/
taskDispatcher.reprocess(holders, result);
break;
case PermanentError:
logger.warn("Discarding {} tasks of {} due to permanent error", holders.size(), workerName);
}
metrics.registerTaskResult(result, tasks.size());
}
} catch (InterruptedException e) {
// Ignore
} catch (Throwable e) {
// Safe-guard, so we never exit this loop in an uncontrolled way.
logger.warn("Discovery WorkerThread error", e);
}
}
/**
* 获取请求任务的集合
* @return
* @throws InterruptedException
*/
private List<TaskHolder<ID, T>> getWork() throws InterruptedException {
/**
* 从acceptor中获取执行任务集合
*/
BlockingQueue<List<TaskHolder<ID, T>>> workQueue = taskDispatcher.requestWorkItems();
List<TaskHolder<ID, T>> result;
do {
/**
* 不断循环等待。直到有新的任务
*/
result = workQueue.poll(1, TimeUnit.SECONDS);
} while (!isShutdown.get() && result == null);
return (result == null) ? new ArrayList<>() : result;
}
/**
* 把List<TaskHolder> 转换到List<Task></>
* @param holders
* @return
*/
private List<T> getTasksOf(List<TaskHolder<ID, T>> holders) {
List<T> tasks = new ArrayList<>(holders.size());
for (TaskHolder<ID, T> holder : holders) {
tasks.add(holder.getTask());
}
return tasks;
}
}
/**
* 每次提交一个任务
* @param <ID>
* @param <T>
*/
static class SingleTaskWorkerRunnable<ID, T> extends WorkerRunnable<ID, T> {
SingleTaskWorkerRunnable(String workerName,
AtomicBoolean isShutdown,
TaskExecutorMetrics metrics,
TaskProcessor<T> processor,
AcceptorExecutor<ID, T> acceptorExecutor) {
super(workerName, isShutdown, metrics, processor, acceptorExecutor);
}
@Override
public void run() {
try {
while (!isShutdown.get()) {
/**
* 从acceptor 线程中拿到请求执行任务
*/
BlockingQueue<TaskHolder<ID, T>> workQueue = taskDispatcher.requestWorkItem();
TaskHolder<ID, T> taskHolder;
/**
* 不断循环等待。直到有任务
* poll()进行等待。最多等待1分钟。
*/
while ((taskHolder = workQueue.poll(1, TimeUnit.SECONDS)) == null) {
/**
* 判断线程释放shutdown了
*/
if (isShutdown.get()) {
return;
}
}
metrics.registerExpiryTime(taskHolder);
if (taskHolder != null) {
/**
* 处理器执行真正的任务处理
*/
ProcessingResult result = processor.process(taskHolder.getTask());
switch (result) {
case Success:
break;
case Congestion:
case TransientError:
/**
* 如果congestion or TransientError
* 进行重试
*/
taskDispatcher.reprocess(taskHolder, result);
break;
case PermanentError:
logger.warn("Discarding a task of {} due to permanent error", workerName);
}
metrics.registerTaskResult(result, 1);
}
}
} catch (InterruptedException e) {
// Ignore
} catch (Throwable e) {
// Safe-guard, so we never exit this loop in an uncontrolled way.
logger.warn("Discovery WorkerThread error", e);
}
}
}
}
源码分析3 TaskProcessor
/**
* An interface to be implemented by clients for task execution.
*
* @author Tomasz Bak
*
* 一个接口被客户端实现 为了任务执行
*/
public interface TaskProcessor<T> {
/**
* A processed task/task list ends up in one of the following states:
* <ul>
* <li>{@code Success} processing finished successfully</li>
* <li>{@code TransientError} processing failed, but shall be retried later</li>
* <li>{@code PermanentError} processing failed, and is non recoverable</li>
* </ul>
*
* 返回任务处理的结果
* 1.Success 任务成功的处理完成
* 2.TransientError 。临时错误。将被重试
* 3.PermanentError。永久的错误。不会被重试
*/
enum ProcessingResult {
Success, Congestion, TransientError, PermanentError
}
/**
* In non-batched mode a single task is processed at a time.
* 一个单一任务呗处理
*/
ProcessingResult process(T task);
/**
* For batched mode a collection of tasks is run at a time. The result is provided for the aggregated result,
* and all tasks are handled in the same way according to what is returned (for example are rescheduled, if the
* error is transient).
*
* 批量任务被处理。
* 结果是由某一个任务的结果决定的。
* 如果有四个任务 有一个失败。则全部失败
*/
ProcessingResult process(List<T> tasks);
}
源码分析4 TaskDispatchers
/**
* See {@link TaskDispatcher} for an overview.
*
* @author Tomasz Bak
* 任务分发器
*/
public class TaskDispatchers {
/**
* 分发给每次处理单一请求的任务执行者
* @param id
* @param maxBufferSize
* @param workerCount
* @param maxBatchingDelay
* @param congestionRetryDelayMs
* @param networkFailureRetryMs
* @param taskProcessor
* @param <ID>
* @param <T>
* @return
*/
public static <ID, T> TaskDispatcher<ID, T> createNonBatchingTaskDispatcher(String id, int maxBufferSize, int workerCount, long maxBatchingDelay, long congestionRetryDelayMs, long networkFailureRetryMs, TaskProcessor<T> taskProcessor) {
/**
* 创建一个acceptor线程。接收任务
*/
final AcceptorExecutor<ID, T> acceptorExecutor = new AcceptorExecutor<>(
id, maxBufferSize, 1, maxBatchingDelay, congestionRetryDelayMs, networkFailureRetryMs
);
/**
* 把acceptor线程接收的任务 交个worker线程进行处理
*/
final TaskExecutors<ID, T> taskExecutor = TaskExecutors.singleItemExecutors(id, workerCount, taskProcessor, acceptorExecutor);
return new TaskDispatcher<ID, T>() {
/**
* acceptor接收任务
* @param id
* @param task
* @param expiryTime
*/
@Override
public void process(ID id, T task, long expiryTime) {
acceptorExecutor.process(id, task, expiryTime);
}
@Override
public void shutdown() {
acceptorExecutor.shutdown();
taskExecutor.shutdown();
}
};
}
/**
* 创建一个处理批量任务的分发器
* @param id
* @param maxBufferSize
* @param workloadSize
* @param workerCount
* @param maxBatchingDelay
* @param congestionRetryDelayMs
* @param networkFailureRetryMs
* @param taskProcessor
* @param <ID>
* @param <T>
* @return
*/
public static <ID, T> TaskDispatcher<ID, T> createBatchingTaskDispatcher(String id, int maxBufferSize, int workloadSize, int workerCount, long maxBatchingDelay, long congestionRetryDelayMs, long networkFailureRetryMs, TaskProcessor<T> taskProcessor) {
/**
* 创建前段接收器。接收任务
*/
final AcceptorExecutor<ID, T> acceptorExecutor = new AcceptorExecutor<>(
id, maxBufferSize, workloadSize, maxBatchingDelay, congestionRetryDelayMs, networkFailureRetryMs
);
/**
* 把acceptor接收的任务分发给worker线程进行处理
*/
final TaskExecutors<ID, T> taskExecutor = TaskExecutors.batchExecutors(id, workerCount, taskProcessor, acceptorExecutor);
return new TaskDispatcher<ID, T>() {
/**
* acceptor接收任务
* @param id
* @param task
* @param expiryTime
*/
@Override
public void process(ID id, T task, long expiryTime) {
acceptorExecutor.process(id, task, expiryTime);
}
@Override
public void shutdown() {
acceptorExecutor.shutdown();
taskExecutor.shutdown();
}
};
}
}