在前文Mesos源码分析(8): Mesos-Slave的初始化中,Mesos-Slave接收到RunTaskMessage消息,会调用Slave::runTask.

 

  1. void Slave::runTask(
  2.     const UPID& from,
  3.     const FrameworkInfo& frameworkInfo,
  4.     const FrameworkID& frameworkId_,
  5.     const UPID& pid,
  6.     TaskInfo task)
  7. {
  8. ……
  9.   // Create frameworkId alias to use in the rest of the function.
  10.   const FrameworkID frameworkId = frameworkInfo.id();
  11.  
  12.   LOG(INFO) << "Got assigned task " << task.task_id()
  13.             << " for framework " << frameworkId;
  14. ……
  15.  
  16.   CHECK(state == RECOVERING || state == DISCONNECTED ||
  17.         state == RUNNING || state == TERMINATING)
  18.     << state;
  19.  
  20.   // TODO(bmahler): Also ignore if we're DISCONNECTED.
  21.   if (state == RECOVERING || state == TERMINATING) {
  22.     LOG(WARNING) << "Ignoring task " << task.task_id()
  23.                  << " because the slave is " << state;
  24.     // TODO(vinod): Consider sending a TASK_LOST here.
  25.     // Currently it is tricky because 'statusUpdate()'
  26.     // ignores updates for unknown frameworks.
  27.     return;
  28.   }
  29.  
  30.   Future<bool> unschedule = true;
  31.  
  32.   // If we are about to create a new framework, unschedule the work
  33.   // and meta directories from getting gc'ed.
  34.   Framework* framework = getFramework(frameworkId);
  35.   if (framework == NULL) {
  36.     // Unschedule framework work directory.
  37.     string path = paths::getFrameworkPath(
  38.         flags.work_dir, info.id(), frameworkId);
  39.  
  40.     if (os::exists(path)) {
  41.       unschedule = unschedule.then(defer(self(), &Self::unschedule, path));
  42.     }
  43.  
  44.     // Unschedule framework meta directory.
  45.     path = paths::getFrameworkPath(metaDir, info.id(), frameworkId);
  46.     if (os::exists(path)) {
  47.       unschedule = unschedule.then(defer(self(), &Self::unschedule, path));
  48.     }
  49.  
  50.     Option<UPID> frameworkPid = None();
  51.  
  52.     if (pid != UPID()) {
  53.       frameworkPid = pid;
  54.     }
  55.  
  56.     framework = new Framework(this, frameworkInfo, frameworkPid);
  57.     frameworks[frameworkId] = framework;
  58.     if (frameworkInfo.checkpoint()) {
  59.       framework->checkpointFramework();
  60.     }
  61.  
  62.     // Is this same framework in completedFrameworks? If so, move the completed
  63.     // executors to this framework and remove it from that list.
  64.     // TODO(brenden): Consider using stout/cache.hpp instead of boost
  65.     // circular_buffer.
  66.     for (auto it = completedFrameworks.begin(), end = completedFrameworks.end();
  67.          it != end;
  68.          ++it) {
  69.       if ((*it)->id() == frameworkId) {
  70.         framework->completedExecutors = (*it)->completedExecutors;
  71.         completedFrameworks.erase(it);
  72.         break;
  73.       }
  74.     }
  75.   }
  76.  
  77.   const ExecutorInfo executorInfo = getExecutorInfo(frameworkInfo, task);
  78.   const ExecutorID& executorId = executorInfo.executor_id();
  79.  
  80.   if (HookManager::hooksAvailable()) {
  81.     // Set task labels from run task label decorator.
  82.     task.mutable_labels()->CopyFrom(HookManager::slaveRunTaskLabelDecorator(
  83.         task, executorInfo, frameworkInfo, info));
  84.   }
  85.  
  86.   // We add the task to 'pending' to ensure the framework is not
  87.   // removed and the framework and top level executor directories
  88.   // are not scheduled for deletion before '_runTask()' is called.
  89.   CHECK_NOTNULL(framework);
  90.   framework->pending[executorId][task.task_id()] = task;
  91.  
  92.   // If we are about to create a new executor, unschedule the top
  93.   // level work and meta directories from getting gc'ed.
  94.   Executor* executor = framework->getExecutor(executorId);
  95.   if (executor == NULL) {
  96.     // Unschedule executor work directory.
  97.     string path = paths::getExecutorPath(
  98.         flags.work_dir, info.id(), frameworkId, executorId);
  99.  
  100.     if (os::exists(path)) {
  101.       unschedule = unschedule.then(defer(self(), &Self::unschedule, path));
  102.     }
  103.  
  104.     // Unschedule executor meta directory.
  105.     path = paths::getExecutorPath(metaDir, info.id(), frameworkId, executorId);
  106.  
  107.     if (os::exists(path)) {
  108.       unschedule = unschedule.then(defer(self(), &Self::unschedule, path));
  109.     }
  110.   }
  111.  
  112.   // Run the task after the unschedules are done.
  113.   unschedule.onAny(
  114.       defer(self(), &Self::_runTask, lambda::_1, frameworkInfo, task));
  115. }

 

最终调用Slave::_runTask

  1. void Slave::_runTask(
  2.     const Future<bool>& future,
  3.     const FrameworkInfo& frameworkInfo,
  4.     const TaskInfo& task)
  5. {
  6.   const FrameworkID frameworkId = frameworkInfo.id();
  7.  
  8.   LOG(INFO) << "Launching task " << task.task_id()
  9.             << " for framework " << frameworkId;
  10.  
  11.   Framework* framework = getFramework(frameworkId);
  12.   const ExecutorInfo executorInfo = getExecutorInfo(frameworkInfo, task);
  13.   const ExecutorID& executorId = executorInfo.executor_id();
  14.  
  15.   if (framework->pending.contains(executorId) &&
  16.       framework->pending[executorId].contains(task.task_id())) {
  17.     framework->pending[executorId].erase(task.task_id());
  18.     if (framework->pending[executorId].empty()) {
  19.       framework->pending.erase(executorId);
  20.       // NOTE: Ideally we would perform the following check here:
  21.       //
  22.       // if (framework->executors.empty() &&
  23.       // framework->pending.empty()) {
  24.       // removeFramework(framework);
  25.       // }
  26.       //
  27.       // However, we need 'framework' to stay valid for the rest of
  28.       // this function. As such, we perform the check before each of
  29.       // the 'return' statements below.
  30.     }
  31.   } else {
  32.     LOG(WARNING) << "Ignoring run task " << task.task_id()
  33.                  << " of framework " << frameworkId
  34.                  << " because the task has been killed in the meantime";
  35.     return;
  36.   }
  37.  
  38.   // We don't send a status update here because a terminating
  39.   // framework cannot send acknowledgements.
  40.   if (framework->state == Framework::TERMINATING) {
  41.     LOG(WARNING) << "Ignoring run task " << task.task_id()
  42.                  << " of framework " << frameworkId
  43.                  << " because the framework is terminating";
  44.  
  45.     // Refer to the comment after 'framework->pending.erase' above
  46.     // for why we need this.
  47.     if (framework->executors.empty() && framework->pending.empty()) {
  48.       removeFramework(framework);
  49.     }
  50.  
  51.     return;
  52.   }
  53.  
  54.   if (!future.isReady()) {
  55.     LOG(ERROR) << "Failed to unschedule directories scheduled for gc: "
  56.                << (future.isFailed() ? future.failure() : "future discarded");
  57.  
  58.     const StatusUpdate update = protobuf::createStatusUpdate(
  59.         frameworkId,
  60.         info.id(),
  61.         task.task_id(),
  62.         TASK_LOST,
  63.         TaskStatus::SOURCE_SLAVE,
  64.         UUID::random(),
  65.         "Could not launch the task because we failed to unschedule directories"
  66.         " scheduled for gc",
  67.         TaskStatus::REASON_GC_ERROR);
  68.  
  69.     // TODO(vinod): Ensure that the status update manager reliably
  70.     // delivers this update. Currently, we don't guarantee this
  71.     // because removal of the framework causes the status update
  72.     // manager to stop retrying for its un-acked updates.
  73.     statusUpdate(update, UPID());
  74.  
  75.     // Refer to the comment after 'framework->pending.erase' above
  76.     // for why we need this.
  77.     if (framework->executors.empty() && framework->pending.empty()) {
  78.       removeFramework(framework);
  79.     }
  80.  
  81.     return;
  82.   }
  83.  
  84.   // NOTE: If the task or executor uses resources that are
  85.   // checkpointed on the slave (e.g. persistent volumes), we should
  86.   // already know about it. If the slave doesn't know about them (e.g.
  87.   // CheckpointResourcesMessage was dropped or came out of order),
  88.   // we send TASK_LOST status updates here since restarting the task
  89.   // may succeed in the event that CheckpointResourcesMessage arrives
  90.   // out of order.
  91.   Resources checkpointedTaskResources =
  92.     Resources(task.resources()).filter(needCheckpointing);
  93.  
  94.   foreach (const Resource& resource, checkpointedTaskResources) {
  95.     if (!checkpointedResources.contains(resource)) {
  96.       LOG(WARNING) << "Unknown checkpointed resource " << resource
  97.                    << " for task " << task.task_id()
  98.                    << " of framework " << frameworkId;
  99.  
  100.       const StatusUpdate update = protobuf::createStatusUpdate(
  101.           frameworkId,
  102.           info.id(),
  103.           task.task_id(),
  104.           TASK_LOST,
  105.           TaskStatus::SOURCE_SLAVE,
  106.           UUID::random(),
  107.           "The checkpointed resources being used by the task are unknown to "
  108.           "the slave",
  109.           TaskStatus::REASON_RESOURCES_UNKNOWN);
  110.  
  111.       statusUpdate(update, UPID());
  112.  
  113.       // Refer to the comment after 'framework->pending.erase' above
  114.       // for why we need this.
  115.       if (framework->executors.empty() && framework->pending.empty()) {
  116.         removeFramework(framework);
  117.       }
  118.  
  119.       return;
  120.     }
  121.   }
  122.  
  123.   if (task.has_executor()) {
  124.     Resources checkpointedExecutorResources =
  125.       Resources(task.executor().resources()).filter(needCheckpointing);
  126.  
  127.     foreach (const Resource& resource, checkpointedExecutorResources) {
  128.       if (!checkpointedResources.contains(resource)) {
  129.         LOG(WARNING) << "Unknown checkpointed resource " << resource
  130.                      << " for executor '" << task.executor().executor_id()
  131.                      << "' of framework " << frameworkId;
  132.  
  133.         const StatusUpdate update = protobuf::createStatusUpdate(
  134.             frameworkId,
  135.             info.id(),
  136.             task.task_id(),
  137.             TASK_LOST,
  138.             TaskStatus::SOURCE_SLAVE,
  139.             UUID::random(),
  140.             "The checkpointed resources being used by the executor are unknown "
  141.             "to the slave",
  142.             TaskStatus::REASON_RESOURCES_UNKNOWN,
  143.             task.executor().executor_id());
  144.  
  145.         statusUpdate(update, UPID());
  146.  
  147.         // Refer to the comment after 'framework->pending.erase' above
  148.         // for why we need this.
  149.         if (framework->executors.empty() && framework->pending.empty()) {
  150.           removeFramework(framework);
  151.         }
  152.  
  153.         return;
  154.       }
  155.     }
  156.   }
  157.  
  158.   // NOTE: The slave cannot be in 'RECOVERING' because the task would
  159.   // have been rejected in 'runTask()' in that case.
  160.   CHECK(state == DISCONNECTED || state == RUNNING || state == TERMINATING)
  161.     << state;
  162.  
  163.   if (state == TERMINATING) {
  164.     LOG(WARNING) << "Ignoring run task " << task.task_id()
  165.                  << " of framework " << frameworkId
  166.                  << " because the slave is terminating";
  167.  
  168.     // Refer to the comment after 'framework->pending.erase' above
  169.     // for why we need this.
  170.     if (framework->executors.empty() && framework->pending.empty()) {
  171.       removeFramework(framework);
  172.     }
  173.  
  174.     // We don't send a TASK_LOST here because the slave is
  175.     // terminating.
  176.     return;
  177.   }
  178.  
  179.   CHECK(framework->state == Framework::RUNNING) << framework->state;
  180.  
  181.   // Either send the task to an executor or start a new executor
  182.   // and queue the task until the executor has started.
  183.   Executor* executor = framework->getExecutor(executorId);
  184.  
  185.   if (executor == NULL) {
  186.     executor = framework->launchExecutor(executorInfo, task);
  187.   }
  188.  
  189.   CHECK_NOTNULL(executor);
  190.  
  191.   switch (executor->state) {
  192.     case Executor::TERMINATING:
  193.     case Executor::TERMINATED: {
  194.       LOG(WARNING) << "Asked to run task '" << task.task_id()
  195.                    << "' for framework " << frameworkId
  196.                    << " with executor '" << executorId
  197.                    << "' which is terminating/terminated";
  198.  
  199.       const StatusUpdate update = protobuf::createStatusUpdate(
  200.           frameworkId,
  201.           info.id(),
  202.           task.task_id(),
  203.           TASK_LOST,
  204.           TaskStatus::SOURCE_SLAVE,
  205.           UUID::random(),
  206.           "Executor terminating/terminated",
  207.           TaskStatus::REASON_EXECUTOR_TERMINATED);
  208.  
  209.       statusUpdate(update, UPID());
  210.       break;
  211.     }
  212.     case Executor::REGISTERING:
  213.       // Checkpoint the task before we do anything else.
  214.       if (executor->checkpoint) {
  215.         executor->checkpointTask(task);
  216.       }
  217.  
  218.       // Queue task if the executor has not yet registered.
  219.       LOG(INFO) << "Queuing task '" << task.task_id()
  220.                 << "' for executor " << *executor;
  221.  
  222.       executor->queuedTasks[task.task_id()] = task;
  223.       break;
  224.     case Executor::RUNNING: {
  225.       // Checkpoint the task before we do anything else.
  226.       if (executor->checkpoint) {
  227.         executor->checkpointTask(task);
  228.       }
  229.  
  230.       // Queue task until the containerizer is updated with new
  231.       // resource limits (MESOS-998).
  232.       LOG(INFO) << "Queuing task '" << task.task_id()
  233.                 << "' for executor " << *executor;
  234.  
  235.       executor->queuedTasks[task.task_id()] = task;
  236.  
  237.       // Update the resource limits for the container. Note that the
  238.       // resource limits include the currently queued tasks because we
  239.       // want the container to have enough resources to hold the
  240.       // upcoming tasks.
  241.       Resources resources = executor->resources;
  242.  
  243.       // TODO(jieyu): Use foreachvalue instead once LinkedHashmap
  244.       // supports it.
  245.       foreach (const TaskInfo& task, executor->queuedTasks.values()) {
  246.         resources += task.resources();
  247.       }
  248.  
  249.       containerizer->update(executor->containerId, resources)
  250.         .onAny(defer(self(),
  251.                      &Self::runTasks,
  252.                      lambda::_1,
  253.                      frameworkId,
  254.                      executorId,
  255.                      executor->containerId,
  256.                      list<TaskInfo>({task})));
  257.       break;
  258.     }
  259.     default:
  260.       LOG(FATAL) << "Executor " << *executor << " is in unexpected state "
  261.                  << executor->state;
  262.       break;
  263.   }
  264.  
  265.   // We don't perform the checks for 'removeFramework' here since
  266.   // we're guaranteed by 'launchExecutor' that 'framework->executors'
  267.   // will be non-empty.
  268.   CHECK(!framework->executors.empty());
  269. }

 

在这个函数中,会调用Framework::launchExecutor去运行一个Executor

  1. // Create and launch an executor.
  2. Executor* Framework::launchExecutor(
  3.     const ExecutorInfo& executorInfo,
  4.     const TaskInfo& taskInfo)
  5. {
  6.   // Generate an ID for the executor's container.
  7.   // TODO(idownes) This should be done by the containerizer but we
  8.   // need the ContainerID to create the executor's directory. Fix
  9.   // this when 'launchExecutor()' is handled asynchronously.
  10.   ContainerID containerId;
  11.   containerId.set_value(UUID::random().toString());
  12.  
  13.   Option<string> user = None();
  14.   // Create a directory for the executor.
  15.   const
    string directory = paths::createExecutorDirectory(
  16.       slave->flags.work_dir,
  17.       slave->info.id(),
  18.       id(),
  19.       executorInfo.executor_id(),
  20.       containerId,
  21.       user);
  22.  
  23.   Executor* executor = new Executor(
  24.       slave, id(), executorInfo, containerId, directory, info.checkpoint());
  25.  
  26.   if (executor->checkpoint) {
  27.     executor->checkpointExecutor();
  28.   }
  29.  
  30.   CHECK(!executors.contains(executorInfo.executor_id()))
  31.     << "Unknown executor " << executorInfo.executor_id();
  32.  
  33.   executors[executorInfo.executor_id()] = executor;
  34.  
  35.   LOG(INFO) << "Launching executor " << executorInfo.executor_id()
  36.             << " of framework " << id()
  37.             << " with resources " << executorInfo.resources()
  38.             << " in work directory '" << directory << "'";
  39.  
  40.   slave->files->attach(executor->directory, executor->directory)
  41.     .onAny(defer(slave, &Slave::fileAttached, lambda::_1, executor->directory));
  42.  
  43.   // Tell the containerizer to launch the executor.
  44.   // NOTE: We modify the ExecutorInfo to include the task's
  45.   // resources when launching the executor so that the containerizer
  46.   // has non-zero resources to work with when the executor has
  47.   // no resources. This should be revisited after MESOS-600.
  48.   ExecutorInfo executorInfo_ = executor->info;
  49.   Resources resources = executorInfo_.resources();
  50.   resources += taskInfo.resources();
  51.   executorInfo_.mutable_resources()->CopyFrom(resources);
  52.  
  53.   // Launch the container.
  54.   Future<bool> launch;
  55.   if (!executor->isCommandExecutor()) {
  56.     // If the executor is _not_ a command executor, this means that
  57.     // the task will include the executor to run. The actual task to
  58.     // run will be enqueued and subsequently handled by the executor
  59.     // when it has registered to the slave.
  60.     launch = slave->containerizer->launch(
  61.         containerId,
  62.         executorInfo_, // Modified to include the task's resources, see above.
  63.         executor->directory,
  64.         user,
  65.         slave->info.id(),
  66.         slave->self(),
  67.         info.checkpoint());
  68.   } else {
  69.     // An executor has _not_ been provided by the task and will
  70.     // instead define a command and/or container to run. Right now,
  71.     // these tasks will require an executor anyway and the slave
  72.     // creates a command executor. However, it is up to the
  73.     // containerizer how to execute those tasks and the generated
  74.     // executor info works as a placeholder.
  75.     // TODO(nnielsen): Obsolete the requirement for executors to run
  76.     // one-off tasks.
  77.     launch = slave->containerizer->launch(
  78.         containerId,
  79.         taskInfo,
  80.         executorInfo_, // Modified to include the task's resources, see above.
  81.         executor->directory,
  82.         user,
  83.         slave->info.id(),
  84.         slave->self(),
  85.         info.checkpoint());
  86.   }
  87.  
  88.   launch.onAny(defer(slave,
  89.                      &Slave::executorLaunched,
  90.                      id(),
  91.                      executor->id,
  92.                      containerId,
  93.                      lambda::_1));
  94.  
  95.   // Make sure the executor registers within the given timeout.
  96.   delay(slave->flags.executor_registration_timeout,
  97.         slave,
  98.         &Slave::registerExecutorTimeout,
  99.         id(),
  100.         executor->id,
  101.         containerId);
  102.  
  103.   return executor;
  104. }

 

会给Task创建一个文件夹里面有Framework和Executor的信息。

最终会调用containerizer->launch。

根据前面Mesos源码分析(7): Mesos-Slave的启动中所说,这里的containerizer是指ComposingContainerizer。

  1. Future<bool> ComposingContainerizer::launch(
  2.     const ContainerID& containerId,
  3.     const TaskInfo& taskInfo,
  4.     const ExecutorInfo& executorInfo,
  5.     const
    string& directory,
  6.     const Option<string>& user,
  7.     const SlaveID& slaveId,
  8.     const PID<Slave>& slavePid,
  9.     bool checkpoint)
  10. {
  11.   return dispatch(process,
  12.                   &ComposingContainerizerProcess::launch,
  13.                   containerId,
  14.                   taskInfo,
  15.                   executorInfo,
  16.                   directory,
  17.                   user,
  18.                   slaveId,
  19.                   slavePid,
  20.                   checkpoint);
  21. }

 

ComposingContainerizer调用ComposingContainerizerProcess::launch

  1. Future<bool> ComposingContainerizerProcess::launch(
  2.     const ContainerID& containerId,
  3.     const TaskInfo& taskInfo,
  4.     const ExecutorInfo& executorInfo,
  5.     const
    string& directory,
  6.     const Option<string>& user,
  7.     const SlaveID& slaveId,
  8.     const PID<Slave>& slavePid,
  9.     bool checkpoint)
  10. {
  11.   if (containers_.contains(containerId)) {
  12.     return Failure("Container '" + stringify(containerId) +
  13.                    "' is already launching");
  14.   }
  15.  
  16.   // Try each containerizer. If none of them handle the
  17.   // TaskInfo/ExecutorInfo then return a Failure.
  18.   vector<Containerizer*>::iterator containerizer = containerizers_.begin();
  19.  
  20.   Container* container = new Container();
  21.   container->state = LAUNCHING;
  22.   container->containerizer = *containerizer;
  23.   containers_[containerId] = container;
  24.  
  25.   return (*containerizer)->launch(
  26.       containerId,
  27.       taskInfo,
  28.       executorInfo,
  29.       directory,
  30.       user,
  31.       slaveId,
  32.       slavePid,
  33.       checkpoint)
  34.     .then(defer(self(),
  35.                 &Self::_launch,
  36.                 containerId,
  37.                 taskInfo,
  38.                 executorInfo,
  39.                 directory,
  40.                 user,
  41.                 slaveId,
  42.                 slavePid,
  43.                 checkpoint,
  44.                 containerizer,
  45.                 lambda::_1));
  46. }

 

上面这个函数可以从第一个containerizer开始,调用它的launch函数,然后再调用ComposingContainerizerProcess::_launch函数。

  1. Future<bool> ComposingContainerizerProcess::_launch(
  2.     const ContainerID& containerId,
  3.     const Option<TaskInfo>& taskInfo,
  4.     const ExecutorInfo& executorInfo,
  5.     const
    string& directory,
  6.     const Option<string>& user,
  7.     const SlaveID& slaveId,
  8.     const PID<Slave>& slavePid,
  9.     bool checkpoint,
  10.     vector<Containerizer*>::iterator containerizer,
  11.     bool launched)
  12. {
  13.   // The container struct won't be cleaned up by destroy because
  14.   // in destroy we only forward the destroy, and wait until the
  15.   // launch returns and clean up here.
  16.   CHECK(containers_.contains(containerId));
  17.   Container* container = containers_[containerId];
  18.   if (container->state == DESTROYED) {
  19.     containers_.erase(containerId);
  20.     delete container;
  21.     return Failure("Container was destroyed while launching");
  22.   }
  23.  
  24.   if (launched) {
  25.     container->state = LAUNCHED;
  26.     return
    true;
  27.   }
  28.  
  29.   // Try the next containerizer.
  30.   ++containerizer;
  31.  
  32.   if (containerizer == containerizers_.end()) {
  33.     containers_.erase(containerId);
  34.     delete container;
  35.     return
    false;
  36.   }
  37.  
  38.   container->containerizer = *containerizer;
  39.  
  40.   Future<bool> f = taskInfo.isSome() ?
  41.       (*containerizer)->launch(
  42.           containerId,
  43.           taskInfo.get(),
  44.           executorInfo,
  45.           directory,
  46.           user,
  47.           slaveId,
  48.           slavePid,
  49.           checkpoint) :
  50.       (*containerizer)->launch(
  51.           containerId,
  52.           executorInfo,
  53.           directory,
  54.           user,
  55.           slaveId,
  56.           slavePid,
  57.           checkpoint);
  58.  
  59.   return f.then(
  60.       defer(self(),
  61.             &Self::_launch,
  62.             containerId,
  63.             taskInfo,
  64.             executorInfo,
  65.             directory,
  66.             user,
  67.             slaveId,
  68.             slavePid,
  69.             checkpoint,
  70.             containerizer,
  71.             lambda::_1));
  72. }

 

ComposingContainerizerProcess::_launch函数会调用下一个Containerizer的launch函数,直到最后一个containerizer。

Mesos源码分析(12): Mesos-Slave接收到RunTask消息的更多相关文章

  1. Mesos源码分析(5): Mesos Master的启动之四

      5. Create an instance of allocator.   代码如下   Mesos源码中默认的Allocator,即HierarchicalDRFAllocator的位置在$ME ...

  2. Mesos源码分析(4) Mesos Master的启动之三

    3. ModuleManager::load(flags.modules.get())如果有参数--modules或者--modules_dir=dirpath,则会将路径中的so文件load进来   ...

  3. Mesos源码分析(6): Mesos Master的初始化

      Mesos Master的初始化在src/master/master.cpp中     在Mesos Master的log中,是能看到这一行的.   1.初始化role,并设置weight权重   ...

  4. Mesos源码分析(2): Mesos Master的启动之一

    Mesos Master的启动参数如下: /usr/sbin/mesos-master --zk=zk://127.0.0.1:2181/mesos --port=5050 --log_dir=/va ...

  5. Mesos源码分析(3): Mesos Master的启动之二

    2. process::firewall::install(move(rules));如果有参数--firewall_rules则会添加规则   对应的代码如下: // Initialize fire ...

  6. Mesos源码分析(1): Mesos的启动过程总论

  7. Mesos源码分析

    Mesos源码分析(1): Mesos的启动过程总论 Mesos源码分析(2): Mesos Master的启动之一 Mesos源码分析(3): Mesos Master的启动之二 Mesos源码分析 ...

  8. Mesos源码分析(11): Mesos-Master接收到launchTasks消息

    根据Mesos源码分析(6): Mesos Master的初始化中的代码分析,当Mesos-Master接收到launchTask消息的时候,会调用Master::launchTasks函数.   v ...

  9. Mesos源码分析(10): MesosSchedulerDriver的启动及运行一个Task

      MesosSchedulerDriver的代码在src/sched/sched.cpp里面实现.     Driver->run()调用start()     首先检测Mesos-Maste ...

随机推荐

  1. (原创)动态内存管理练习 C++ std::vector<int> 模拟实现

    今天看了primer C++的 “动态内存管理类”章节,里面的例子是模拟实现std::vector<std::string>的功能. 照抄之后发现编译不通过,有个库函数调用错误,就参考着自 ...

  2. vscode插件解析-BookMark

    BookMark (书签):在编辑器中标记行并轻松跳转到它们. commands 书签:Toggle   标记/取消标记带书签的行 书签:Jump to Next  将光标向前移动到下面的书签 书签: ...

  3. iOS UINavigationController Class Translation

    类   UINavigationController 一个容器视图控制器,定义了用于导航分层内容的基于堆栈的方案.   概述   导航控制器是一个在导航界面中,管理一个或多个子视图控制器的容器视图控制 ...

  4. spring security 学习一

    1.配置基本的springboot web项目,加入security5依赖,启动项目 浏览器访问,即可出现一个默认的登录页面 2.什么都没有配置 登录页面哪里来的 一般不知从何入手,就看官方文档里是如 ...

  5. BLO(bzoj1123)

    Description Byteotia城市有n个 towns, m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n和 ...

  6. js object数据类型

    1.object数据类型,[可以]认为JavaScript中顶级数据类型.在JavaScript绝大多数 高级类型对象都是object类型 2.如何创建一个object类型对象 1) 通过调用Obje ...

  7. C#应用编程小例子-03-展示另一个窗体

    C#应用编程小例子-03-展示另一个窗体 using System; using System.Collections.Generic; using System.ComponentModel; us ...

  8. pip命令

    安装包 pip install django   #最新版本 pip install django==1.11.7 #指定版本 pip install django>=1.11.7 #最小版本 ...

  9. Linux禁止普通用户su至root

    linux系统为了限制权限,有时候需要禁止普通用户su到root用户 为禁止普通用户su至root,需要分别修改/etc/pam.d/su和/etc/login.defs两个配置文件. 二.详细配置 ...

  10. Python学习最佳路线图

    python语言基础(1)Python3入门,数据类型,字符串(2)判断/循环语句,函数,命名空间,作用域(3)类与对象,继承,多态(4)tkinter界面编程(5)文件与异常,数据处理简介(6)Py ...