Mesos 提供了集群化的资源管理功能。 为了将实际业务与 Mesos 结合起来,就需要用到 Mesos Framework(Mesos 框架),即基于 Mesos 的应用。

基于官方的 Mesos 框架示例代码,我们来分析看框架的基本结构,并了解社区已有框架的现状。

Mesos 源码发布的 Demo 有 C++/Java/Python 三种实现。 我们选取其中的 Python 和 Java 代码来学习框架的基本代码结构。

今天的学习内容有:

  • Mesos Framework 基础知识
  • Mesos Demo 源码分析(Java和Python)
  • Mesos Frameworks 现状概览

Mesos Framework 基础知识

Framework Development Guide 是了解基础知识最直接的文档。

基本要求

Mesos 框架主要实现 scheduler 的接口,其中定义 executor 的细节。

每一个 Mesos Framework 的实现都需要满足以下要求:

  • 实现一个调度器类,需要继承 Scheduler 类
  • 创建一个 SchedulerDriver 实例,用于框架和 Mesos 之间通讯,并执行 SchedulerDriver.run()

Framework 初始化流程

框架初始化时需要做一系列准备工作。 Framework 初始化的流程可以用下图表示:

Mesos Framework Init

开发框架时,只需按照以上顺序实例化相应的类,并在最后一步调用 SchedulerDriver.run

Scheduler API

调度器的实现部分,是框架的主要开发工作。

框架的调度器需要实现 Scheduler 预先定义的的回调接口。 接口定义在 include/mesos/scheduler.hpp 这个文件中。

以下为每个接口被调用时期的简要说明:

  • registered: 调度器在 mesos master 上注册成功时
  • reregistered: 发生 mesos master 重新选举后,将调度器注册到新的 mesos master
  • disconnected: 调度器从 mesos master 断开时,如 master 进程挂掉而新的 master 尚未选出时
  • resourceOffers: master 分配资源给框架时。注意:
    • 每次分配只包含一个 slave 节点的资源
    • 在框架使用资源之前,不会再被提供同一资源。除非框架拒绝使用这些资源,或者资源被取消
    • 资源可能被同时分配给多个框架,因此只有第一个使用资源的框架能成功,其它的任务将以 TASK_LOST 状态失败
  • offerRescinded: 资源不可用/被取消时
  • statusUpdate: 计算任务的状态发生变化
  • frameworkMessage: executor 发送了消息
  • slaveLost: slave 变为不可用
  • executorLost: executor 退出或被终止
  • error: scheduler 或者 scheduler driver 发生不可恢复错误后
SchedulerDriver API

SchedulerDriver 的接口一般不需要自行实现。 可以直接使用 MesosSchedulerDriver。

Mesos Demo 源码

Java:Scheduler 类里重要的接口实现

以下选几个重要的接口来研究。

resourceOffers

这个回调函数实现的功能分为三个阶段,分别是:

  • 第一阶段,先计算这一批获得的资源量。    如果资源足够启动至少一个 task,则执行下一步。
  • 第二阶段,启动新的 task,从资源池分配资源给新建的 task。重复创建 task 直至资源不足。
  • 第三阶段,将所创建的进程信息,和使用的资源,通过 driver 标记为已用 driver.acceptOffers(offerIds, operations, filters);

这个过程的示意图如下:

Mesos Framework Scheduler Workflow

定位到对应代码

    public void resourceOffers(SchedulerDriver driver,
                               List<Offer> offers)

注意这里面的创建 task 时的关键代码,展示了如何创建 task。

          TaskID taskId = TaskID.newBuilder()
            .setValue(Integer.toString(launchedTasks++)).build();

          TaskInfo task = TaskInfo.newBuilder()
            .setName("task " + taskId.getValue())
            .setTaskId(taskId)
            .setSlaveId(offer.getSlaveId())
            .addResources(Resource.newBuilder()
                          .setName("cpus")
                          .setType(Value.Type.SCALAR)
                          .setScalar(Value.Scalar.newBuilder().setValue(CPUS_PER_TASK)))
            .addResources(Resource.newBuilder()
                          .setName("mem")
                          .setType(Value.Type.SCALAR)
                          .setScalar(Value.Scalar.newBuilder().setValue(MEM_PER_TASK)))
            .setExecutor(ExecutorInfo.newBuilder(executor))
            .build();

          launch.addTaskInfos(TaskInfo.newBuilder(task));
statusUpdate

定位到对应代码

    public void statusUpdate(SchedulerDriver driver, TaskStatus status)

当状态为 TASK_FINISHED 时,统计完成的 task 数量,决定是否结束框架的运行。 当状态为 TASK_LOST/TASK_KILLED/TASK_FAILED 时,则做了不同的处理,使用driver.abort直接终止了框架的运行。

Java:Framework 初始化的过程

前面提到了框架初始化的过程。 下面主要看一下 driver 初始化的代码。

driver 初始化

关注测试类的主函数中,MesosSchedulerDriver 的用法。

      driver = new MesosSchedulerDriver(
          scheduler,
          frameworkBuilder.build(),
          args[0],
          implicitAcknowledgements,
          credentialBuilder.build());
    }

driver 初始化之后,执行 driver.run 就可以更新到框架执行的状态。

Python Demo

Python Demo 的实现的功能与 Java 基本一致。 从代码上可以看到 Python 发挥了语法的优势,节省了比较多代码量。 多语言的接口实现一致性也是项目采用 Protocol Buffers(protobuf) 之后的一大优势。

Python 代码不具体列出了,学习是重点关注自定义 Schedule 类的实现和框架初始化过程。

Demo 学习总结

通过观察现有的 Demo 实现,我们学习了一个简单 Framework 的基本代码结果,有利于以后学习更多的框架实现。

另外,使用 Mesos Command Executor 可以很容易创建基于命令行的任务,由于非常方便,所以应用非常广泛。

Mesos Framework 现状

Mesos 官网的 Software Projects Built on Mesos 页面列出了基于 Mesos 的一些流行框架。 这些框架的种类涵盖了大数据平台、批处理系统、数据存储、长期运行的服务和运维平台。 我们可以方便的使用这些框架集成到自有的系统中。

后面的学习过程中,我们还会比较多的接触一些常用框架,比如 Marathon、Chronos、Vamp 等。

由于 Mesos 框架使用方便,资源调度很容易,对运维人力有显著的解放左右,也让组织可以更顺畅的建设构建发布流程。

总结

本文主要对 Mesos Framework 的官方 Demo 进行了简要分析。 通过代码的学习,帮助我们了解 Mesos Frameworkd 基本结构,既有益于以后开发自己的框架,也有助于使用社区的其它框架时方便理解设计的原理。