Eureka 源码分析 - 节点同步执行框架

介绍


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();
           }
       };
   }
}

猜你喜欢

转载自blog.csdn.net/ai_xiangjuan/article/details/80155329
今日推荐