原文地址
http://mesos.apache.org/documentation/latest/high-availability-framework-guide/
阅读建议:有写过或者看过Mesos Framework的开发者,或者对Mesos有较多了解的使用者,文章的部分其实包含了分布式系统设计的一些通用的思路。对于分布式系统感兴趣的人也适合本文。
我基于本文改进了本身的框架的可用性,很是有效。另外Mesos支持restful接口,基于Restful接口,咱们能够采用更加稳定的、开源的一些服务来代替本身设计的框架,好比使用PHP服务器来管理。mysql
agent或者客户端 其实文章中多数状况下指的就是Mesos-Slavesql
网络隔离:或者网络割接描述一种网络不可达或者不可用的状况。数据库
翻译的不专业,敬请谅解。。。会逐步改进。apache
Mesos框架是用来管理任务的。为了让框架有高的可用性,它必须可以在多种失败的场景下继续管理任务。做为一个框架的开发者你须要关注的常见状况以下:服务器
请注意,这些问题有可能同时发生。restful
在讨论以上失效场景以前,有必要强调一下Mesos 是如何设计并影响高可用性的:网络
Mesos在组件之间提供了一种不可靠的消息:消息被最多递送一次(可能被丢掉)。框架设计者应当考虑到发送的消息可能没有被收到而且准备好适当的矫正工做。为了定位这个问题,框架的Scheduler 应该设计一个超时时间用于判断新的task是否被生成。若是在超时后 Scheduler没有看到新任务的状态更新,它应该开始矫正。好比,调节任务状态(为失效),而后若是有必要,从新启动一个任务。架构
通常来讲,分发系统没法区分消息是“丢失”仍是“延时”。在上面的例子中,Scheduler可能在超时后收到状态更新信息,而且已经开始进行校订工做了。因此框架设计者应该考虑到这种状况发生的而可能性而且为此在程序上作好适配。框架
Mesos事实上在进程之间提供一种有序的的(可是不可靠)的消息递送:好比若是框架发送M1 和 M2给master,那么框架将收到:没有任何消息,只有M1 或 M2,M1 而后 M2 ,可是必定不会收到M2 而后 M1。tcp
为了方便框架开发者,Mesos提供了可靠的任务状态更新机制(谢天谢地)。客户端会将状态更新持久化到磁盘上而后发送到master。master将状态发送到合适的Framework Scheduler。当一个Scheduler认可状态更新,master会将这种认可发还给客户端,这样容许保存状态更新的存储进行垃圾回收。若是客户端在必定时间内没有收到状态更新的确认,它会重复发送状态更新给master(这里要当心),一样也会再发给Scheduler。因此,假设客户端和Scheduler都是可用的状况下,任务的状态更新是“至少”发送一次。要想应付任务状态可能发送超过一次的状况,将Framework Scheduler的处理逻辑设计成幂等(每次结果都同样)是很是有用的。
Mesos master 将注册的框架和活动的任务的信息都保存在内存里:并无持久化到磁盘上或者试图在master失效后依旧保持这些数据。这帮助Mesos master 经过许多的任务和框架,扩容为大型的集群。这个设计的一个负面影响就是在失效后,须要更多的工做来恢复在内存中丢失的数据。
若是Mesos master 不可用(宕机或者断网什么的),集群将继续运做:当前的Mesos 客户端和用户的任务将继续运行。可是,新的任务没法被调度,framework将不会收到资源的offers或者来自于以前启动过的任务的状态更新信息。
Mesos 并不规定framework应该如何实现,也不为框架如何处理失败状况承担任何责任。取而代之,Mesos 尽力提供框架的开发者他们须要的工具去实现这些特性。不一样的框架可能在处理失效的问题上采用不一样的方案,这取决于他们的实际状况。
一个高可用的框架能够按照下面的一些通用方案来设计:
为了容忍Scheduler失效,框架应该同时运行多个Scheduler 实例(一般是3个)。在任什么时候候,只有一个实例是他们的头头:这个实例和Mesos master链接着。接受资源分配和任务状态更新,启动新的任务。其余的Scheduler只是随从:他们只在头头挂掉的时候被使用,在这种状况下,其中之一被选为新的头头。
Scheduler们须要有个机制来判断当前的头头挂了而且选举一个新的头头。常见的是使用一些协调服务好比zookeeper。查看你使用的协调服务器的文档来获取更多的关于如何实现头头选举的功能。
当一个Scheduler当选为新的头头,新头头要从新和Mesos master链接。当注册到master的时候,框架应该和以前失效的框架使用同一个ID。这确保master会认识到这个链接并非一个新的会话,而是继续以前的失效Scheduler的会话。
注意:当旧的scheduler 头头失效的时候,默认状况下master会立刻杀掉全部的和framework有关的任务和Executors。一个典型的生产环境框架,这个默认行为是不可容忍的。要避免这个状况,高可用的框架应该设置failover_timeout字段一个很是大的值。为了不在生产环境中之外破坏任务,许多框架将failover_timeout设置为1个星期甚至更多。
在从新链接Mesos master以后,新的头头应该确保本地环境状态和整个集群保持一致。好比,假设以前的头头正好要启动一个新的任务,而后挂了。这个任务应该可以继续启动成功,而且在这里新选举的头头将会收到这个任务状态更新。为了应对这个状况,framework通常使用一种有健壮的一致性的分布式数据存储来记录这些关于活动或暂停的任务信息。事实上,用于头头选举的工具zookeeper也能够用于这个目的。一些Mesos框架使用Mesos 日志副原本达到这个目的。
Scheduler必须在执行任务前将“意图”落地:不然可能失去了写入的机会(其他不翻译,都是这个状况会有多糟糕)。
Scheduler必须确保“意图”可以确实记录到数据存储中,在继续启动任务以前(一些分布式数据库好比Cassandra 可能在写入一个备份就返回成功了,其余节点可能尚未写入)
TASK_STARTING是可选的,是自定义Executors的首要选择。它用于描述自定义Executor已经知道了任务(可能已经在读取资源了)可是尚未跑起来。
一个任务在确实运行成功后,发送TASK_RUNNING状态(若是失败了,须要发送一些失败的状态,后面会列出)
当一个framework企图要启动一个任务可是在超时后并无收到状态更新时,framework须要进行适配。它须要主动询问Master这个task如今的状态。针对未知的任务master会回复TASK_LOST。framework能够用这个区分tasks是启动慢了仍是master没有递送启动请求(好比请求被丢弃了)
注意这个技术的正确性是基于Scheduler和master直接的消息通讯是有序的。
TASK_FINISHED 任务正常结束或者关闭
TASK_FAILED 任务由于错误被关闭
TASK_KILLED Executor杀掉了任务
TASK_LOST 暗示任务有在跑,可是master监控不到,将来会废弃
TASK_ERROR 启动的时候就挂了
Mesos master使用2种不一样的机制追踪客户端的可用状况和健康状况
若是和客户端的TCP的长链接断开或者健康检查失败(注意是或)。master就认为节点挂了,而且任务呗移除除了集群。
特别的:
若是tcp链接断开,agent被认为没法链接。The semantics when a registered agent gets disconnected are as follows for each framework running on that agent:
若是tcp断开,客户端断开
若是framework在检查点:没有立刻要执行的操做。客户端有机会再超时以前再次连上。
若是framework不在检查点:全部的framework的任务和Executors都被认为丢失了。master会立刻为任务发送一个TASK_LOST状态。这个更新将不会可靠的递送给Scheduler(说好状态是可靠的。。。注意下面的提示)。客户有一个机会在健康检查超时前从新链接。若是agent重连,任何发出的TASK_LOST状态更新消息会被kill(原来如此)。
这种行为模式的根本缘由是,使用典型的TCP设置,master和angent 之间TCP持久链接的错误更倾向于客户错误(好比slave进程被中断)而不是网络隔离,由于Mesos的健康检查超时比典型的TCP-level的超时要来的小的多。由于不在检查点的framework将不会 survive a restart of the mesos-slave process,master发送TASK_LOST状态更新这样这些任务能够被从新调度。Of course, the heuristic that TCP errors do not correspond to network partitions may not be true in some environments.
若是一个agent在健康检查(health checks)中失败了,它会被计划移除。移除的速度能够有master控制(--slave_removal_rate_limit master 配置)以免移除一次性移除一系列的子节点(好比在网络切割的时候)。
当移除一个客户端,master将会给客户端打个removed的标记,并记录在持久化状态中(master失效后也在)。master发送slavelost callback 给每个已注册的scheduler driver;也会发送每个在这个客户端运行的任务的TASK_LOST 状态更新
注意:master发送的不管是callback仍是状态更新,都不是可靠的。好比,master或者Scheduler挂了或者网络链接在发送的时候异常,他们不会重发!
同时,任何一个移除的客户端的任务会继续跑,并且客户端会尝试从新链接master。若是移除的客户端可以重连到master(好比网络链接又恢复了,shit),从新注册的请求会被拒绝,并且客户端会被要求关闭。客户端会关闭全部的正在跑的任务和executor,移除的客户端上面的持久化volumes 和 dynamic reservations 将被保护(不理解)。
一个移除的客户端在启动一个新的mesos-slave进程后能够从新加入集群。当移除的客户端被master关闭时,Mesos确保下一次mesos-slave 启动的时候(使用同一个工做目录和同一个host),客户端会获得一个新的agent ID;结果就是,客户端会被当作一个全新的客户端加入集群。agent将会保留以前建立的持久化volumes 和 dynamic reservations,虽然连接这些资源的angent ID已经变了。典型状况下,框架在应对失效或者隔离的客户端的时候会调度失效客户端上的任务到其余地方。这须要很是当心,尽管失效的客户端可能还活着,可是和master隔离而且没法通信。依赖天然的网络隔离,客户上的任务可能仍是能够和其余客户端或者集群节点通信。Framework能够作些事情来避免这个状况(好比,使用zookeeper来中止agent工做,若是他们的zk链接仍是正常的),可是Mesos将这些细节留给了框架开发者。
上面描述的行为在一个新的Mesos master刚被选举完的一段时间中是不会被执行的。上面会注意到,多数的Mesos master状态仅保存在内存中。同时,当当前master失效,新的master 选举后,新的master只有当前集群的极少数信息。取而代之,他重建他的信息经过通知 framework 和 客户端新master被选举,并从新注册到它上面。
当一个master失效发生,链接在以前的master的framework须要链接到新的master上。MesosSchedulerDriver 持有多数细节of决定何时先前的master失效,何时链接到新的master上;当framework成功注册到新的master上, “reregistered scheduler driver callback”(一个回调函数) 将被调用。
当一个新的master被选举后的一个时期内,在给定的客户端从新注册以前或者slave_reregister_timeout被触发,尝试调试在这个客户端上面的任务状态将不会反回任何信息(由于master还不能确切知道任务状态)
若是一个客户端在必定时间 (controlled by the --slave_reregister_timeout configuration flag),内没有从新注册到新的master上,master会标记这个agent为失效而且和上面说的失效流程处理相同。可是,有一个不同,默认状况下,客户端被容许重连到失效的master节点,即便在slave_reregister_timeout被触发后。也就是说,framework可能看到TASK_LOST 的任务状态更新,可是过一会发现任务其实在跑(觉得这个客户端是容许重连的)。这个行为能够避免,经过容许--registry_strict 这个选项。这个选项在未来的Mesos版本中,会变成默认值。