mesos-execute
src/cli/execute.cpp
这也是如何写自己的framework的一个很好的例子。
启动
- 676-736:处理命令行参数
- 740-792:处理HDFS。。。。。。。。
- 794-807:如果命令行指定了APPC或是DOCKER的映像。。。。。
- 810-832:设置framework的初始Capability为TASK_KILLING_STATE,再根据命令行参数
--framework_capabilities
指定的值设置Capability - 835-849:设置volumes
- 851-858:初始化frameworkInfo,设置user,name,role等
- 860-871:如果命令行提供了认证信息,也进行相关设置
- 873-889:创建scheduler
- 891:启动
- 892:等待结束
CommandScheduler类
CommandScheduler类定义
私有变量定义在654-670行:
- master
- name
Owned<Mesos> mesos
(Mesos对象,这里不是指针。Owned见libprocess)
Mesos对象对应的是mesos::v1::scheduler::Mesos
CommandScheduler:initialize
新建一个Mesos对象,传递了三个函数作为回调函数(298-300)。再调用mesos.reset初始化,这里的Mesos对象对应的是mesos::v1::scheduler::Mesos,见辅助对象,mesos.reset将对象的引用计数重置。
此处Mesos对象对应的是mesos::v1::scheduler::Mesos
,见81行。
doReliableRegistration
- 318-320:若是SUBSCRIBED/DISCONNECTED状态,则返回
- 322-323:构造一个Call,类型为Call::SUBSCRIBE
- 325-327:若有framework ID,则拷贝到Call
- 329-330:拷贝frameworkInfo
- 332:调用mesos->send(call)
- 334:延迟一秒后,再调用本函数?????
received
当收到事件消息时被调用
- 460:事件队列不为空就一直处理
- 461-462:从事件队列取出一个事件event
- 464:根据事件类型处理:
- 465-473:SUBSCRIBED,记录下framework ID???
- 475-478:OFFERS,调用offers函数
- 480-483:UPDATE,调用update函数
- 485-490:ERROR,调用EXIT。。。。。。。
- 492-504:HEARTBEAT/INVERSE_OFFERS/FAILURE/RESCIND/RESCIND_INVERSE_OFFER/MESSAGE,这些只是master给来的应答信息,无须处理
- 501-504:UNKNOWN,不认识的信息,报警告
offers
当收到OFFERS消息时被调用
参数:
const vector<Offer>& offers
:offers向量357:确保当前状态为SUBSCRIBED
- 359-365:解析resources(resources是CommandScheduler类的私有变量,定义在660行,若命令行未指定(见881行),则默认是"cpus:1;mem:128",见121-124行)
- 367:对offers中每一个offer处理:
- 368:得到offer中的资源
- 370:若还未启动且offer中已经含有任务运行需要的资源:
- 372-374:设置任务名称、agent ID
- 377-378:根据framework指定的role从offer中寻找对应的资源
- 380:确保资源已经找到
- 382:资源信息拷贝到任务中
- 384-394:设置commandInfo,shell
- 396-406:设置环境变量
- 408-410:设置URI?????
- 412-421:拷贝容器相关信息
- 423-424:初始化一个Call对象,类型为ACCEPT
- 426:确保framework ID已经设置
- 429-430:设置call.accept的offer ID为刚收到的offer ID
- 432-435:设置call.accept的操作为LAUNCH,并拷贝任务相关信息
- 437:发送消息给master
- 442:设置launched=true
- 444-453:否则,资源不满足要求,设置CALL类型为DECLINE,并发送消息给master
资源Resources定义在include/mesos/v1/resources.hpp,实现在src/common/resources.cpp
update
当任务状态更新时被调用
- 511-512:当前状态必须为SUBSCRIBED,任务ID与收到的状态消息中的ID必须一致
- 514-527:输出状态消息的一些信息到标准输出
- 529-541:若状态消息中含有UUID,则回复一个ACKNOWLEDGE的消息,为什么???
- 545-551:若定义了killAfter,则延迟killAfter定义的时间后调用killTask
- 553-555:若检测到任务状态已经是终止(收到master发来的消息TASK_FINISHED),则调用terminate终止自己。因为本命令只启动一个task。
killAfter是在命令行传入的,表示多久之后会自动将任务杀掉,格式类似:10secs,2mins等
Mesos类
定义在include/mesos/v1/scheduler.hpp,这个对象是mesos对scheduler的接口。
Mesos(const std::string& master,
ContentType contentType,
const std::function
这里定义了三个回调函数:
- 连接
- 断连
- 收到master发来的事件
Mesos类还有几个函数:
- send:发送一个调用给master。scheduler只应在收到connected回调时调用本函数
- reconnect:强迫与master重连
及一个私有变量:MesosProcess* process
构造函数Mesos::Mesos
src/scheduler/scheduler.cpp
- 749-758:读取标志
- 760-768:设置私有变量process为新的MesosProcess对象
- 770:启动process
Mesos的其他函数
send/reconnect:在process上调用MesosProcess::send/reconnect
MesosProcess类
这个process是负责发送HTTP消息到master或者是从master接收HTTP消息
构造函数
- 154:初始化libprocess
- 156-163:如果是在LOOPBACK接口上,输出警告
- 166-170:初始化LOG
- 176-179:若master是"local",则调用local::launch。若命令行未指定master则master是"local"
- 181-190:若
_detector
为空,则创建一个detector,并调用reset,作用是?????? - 191-193:否则得到detector
initialize
299-300:调用detector(对应zookeeper.cpp或standalone.cpp)检测master,调用MesosProcess::detected
detection = detector->detect()
.onAny(defer(self(), &MesosProcess::detected, lambda::_1));
void detected(const Future<Option<mesos::MasterInfo>>& future)
- 413-416:判断是否已经失败(什么时候失败??????)这个探测也是异步动作
- 418-425:若状态是CONNECTED/SUBSCRIBING/SUBSCRIBED,表示之前已经连接,调用断连。
- 428:断连
- 430-439:若future(异步MasterInfo)已经被discard或不存在,将master设为None。这种情况的例子可见standalone.cpp,当StandaloneMasterDetectorProcess调用discard时。
- 440-452:使用HTTPS吗?
- 454-459:得到master对应的URL,URL是/master/api/v1/scheduler
- 463:使用一个随机的UUID作为connectionId
- 467-468:计算一个0-flags.connectionDelayMax(默认是500ms)之间的随机数作为延迟
- 473:延迟一段时间后调用MesosProcess::connect
- 477-478:每隔一段时间再调用自己(detected),确保当master意外退出,或产生新的master时能够及时连接上。
void connect(const UUID& _connectionId)
- 307-310:参数
_connectionId
必须和初始化时记录的connectionId一致,否则返回 - 312:状态必须为DISCONNECTED
- 313:master必须已经设置
- 315:状态设置为CONNECTING
- 317-319:设置一个连接函数connector,它调用process::http::connect,连接master
- 323-324:????调用两次connector,得到两个connection,对每个connection,调用connected,这些都是异步的。。。。
collect(connector(), connector()) .onAny(defer(self(), &Self::connected, connectionId.get(), lambda::_1));
void connected
参数:
- const UUID& _connectionId
- const Future
>& _connections)
这里定义了两个连接,一个是用于subscribe,一个是用于non-subscribe,定义见116行。
- 333-336:检查连接ID
- 338:检查状态
- 339:连接ID必须已经设置
- 341-347:两个连接变量若未准备好,则断连,并给出断连原因
- 351:状态改为CONNECTED
void send(const Call& call)
- 210-229:判断各种错误
- 237-251:构建POST请求,包括请求内容(支持PROTOBUF和JSON两种格式),认证信息
- 253:确保connections已经初始化
- 256-260:若Call的类型是SUBSCRIBE,则从connections->subscribe发送请求
- 261-268:否则从connections->nonSubscribe发送请求,这种情况要带上Mesos-Stream-Id,不知做什么用????????
- 270-275:当应答就绪,调用
_send
_send
参数:
- _connectionId
- call
- response
流程:
- 514-516:判断连接ID未发生变化
- 518-528:检查状态,检查response是否还可用
- 530-556:如果返回的response是“200 OK”,则:
- 536:将状态改为SUBSCRIBED
- 538:得到reader
- 540-544:构建解码函数
- 546-555:读response内容并返回
- 。。。。。。。。。。
mesos-containerizer
src/slave/containerizer/mesos/main.cpp
只有这几行代码:
return Subcommand::dispatch(
None(),
argc,
argv,
new MesosContainerizerLaunch(),
new MesosContainerizerMount(),
new NetworkCniIsolatorSetup());
Subcommand的定义在: 3rdparty/stout/include/stout/subcommand.hpp
三种命令的定义,都是继承Subcommand类,定义都在目录下:
类名称 | 定义文件 |
---|---|
MesosContainerizerLaunch | src/slave/containerizer/mesos/launch.hpp |
MesosContainerizerMount | src/slave/containerizer/mesos/mount.hpp |
NetworkCniIsolatorSetup | src/slave/containerizer/mesos/isolators/network/cni/cni.hpp |
MesosContainerizerLaunch:
MesosContainerizerLaunch::NAME = "launch"
MesosContainerizerMount::NAME = "mount";
MesosContainerizerMount::MAKE_RSLAVE = "make-rslave";
NetworkCniIsolatorSetup::NAME = "network-cni-setup"
MesosContainerizerLaunch的构造函数只是调用Subcommand(NAME)
在Subcommand构造命令后,调用subcommand->execute,该虚函数由各个具体的类实现。
因此,这里大约是会依次调用MesosContainerizerLaunch::execute、MesosContainerizerMount::execute、NetworkCniIsolatorSetup::execute
MesosContainerizerLaunch::execute
- 111-114:要有
--command
标志的定义 - 116-124:读写管道要同时可用,或都不可用
- 127-146:解析命令
- 148:若定义了管道
- 149-164:处理管道相关操作。。。。。。
- 167-170:一直在pipe[0]上等待,等待该管道有另外的进程写入内容,以启动本进程
- 172-178:内容要符合特定的长度,否则报错退出
- 180-184:关闭管道pipe[0]
- 187-195:若标志中有unshare_namespace_mnt,调用相关操作。。。。
- 199-202:若定义了pre_exec_commands,对pre_exec_commands中定义的每一条执行以下操作:
- 203-206:若是不合法的JSON格式,报错返回
- 208-218:解析JSON
- 222-235:调用subprocess生成新的进程,并执行程序
- 243:等新进程执行结束
- 245-254:若新进程的退出状态有错,则返回失败
- 273-303:若定义了用户,获取用户ID
- 310:得到根文件系统路径
- 314-343:若定义了根文件系统路径,调用chroot
- 349-370:设置各种用户ID。。。。。。
- 373-381:改变进程的工作目录
- 386-397:执行exec,不再返回