女主宣言
今天女主给大家带来的是360云平台的一项很重要的功能 —— Qcmd 任务分发系统。
PS:丰富的一线技术、多元化的表现形式,尽在“
HULK一线技术杂谈
”,点关注哦!
Qcmd 是360云平台底层的命令执行系统,详细介绍请查看
《深度剖析360命令执行系统Qcmd》
,为了让 Qcmd 能够更好的为业务提供服务,我们在 Qcmd 的上层封装了一层 Qcmd-http 任务分发系统,Qcmd-http 系统同样采用 Golang 编写。它主要负责以下几个事情:
-
实现 qcmd 的集群分布式,维护 qcmd 集群的高可用。
-
支持更复杂的任务类型以满足复杂的业务场景。
-
将业务与底层的 qcmd 彻底解耦。
首先,让我们在360云平台上,从页面的视角来观察一下整个执行的过程吧。
-
选择脚本,选择要执行的主机,执行任务。
注:zjl.sh 脚本是我随手写的,里面执行的是查看当前主机名的命令
-
任务的状态会经过处理中到执行成功,在任何时候,你都可以点击查看按钮来观察任务执行的当前状态以及每个 minion 的任务执行结果。
-
minion,直译过来是奴才的意思,表示最终要执行任务的主机。比如你要执行一个
hostname
的命令,最终是在 minion 主机上执行的。
-
master,直译过来是主人的意思,表示接收业务方任务请求,下发给 minion 主机执行,并收集 minion 执行结果,将结果反馈给业务方的主机。
-
集群,为了维护系统的高可用,通常我们不会将 master 的系统只部署在一台机器上,实际上,我们目前是部署在2台主机上,这两台 master 主机以及他们下面连接的 minion,我们称它为一个集群,具体集群的状态以及工作机制,稍后会有详细地介绍。
-
分布式,如果只有一个集群,当 minion 的主机数据日渐增多时,master 的压力会比较大,而且北京的 master 给上海的 minion 下发任务,理论上肯定不如北京的 master 下发到北京的 minion 来的快,所以为了高性能并且去中心化,我们以机房为维度搭建了多个集群, 以达到不同的集群服务于不同的 minion 的作用,详见下面的分布式集群拓扑。
-
分布式集群拓扑
-
集群拓扑
-
master 的状态
master 的结构是一主一从(也可以是一主多从),minion 与集群中的所有 master 都保持着连接,只有主 master 提供对外服务,qcmd-http 系统在数据库维护着 master 与集群的关系,以及 master 的主从状态,一旦主master出现故障,可以将从 master 与主 master 的角色互换,新的主 master 会继续提供对外的服务。
-
minion 的状态
minion 的状态也有两种,up 和 down,主 master 每隔一段时间会给已经通过认证的 minion 主机发送 test-ping 心跳包,来获取当前 minion 的存活状态,如果 minion 主机down 掉了,会通知 qcmd-http 分发系统,分发系统在数据库中将此 minion 的状态置为 down。
线上业务的任务不只是执行
hostname
这样简单的一条命令,为了满足绝大多数的业务使用场景,qcmd-http 分发系统支持了4种不同类型的任务
-
单任务-串行阻塞,比如你要在minion-01,minon-02,minion-03三台主机上执行命令
hostname
,但是你想让 minion-01 主机先执行,如果 minion-01 主机执行成功了,再执行 minion-02 主机,如果 minion-01 主机执行失败了,那么任务就终止了。
-
单任务-串行非阻塞,与单任务的串行阻塞的原理相似,只不过当 minion-01 主机执行失败时,任务会继续往下执行,并不会终止,直到所有的 minion 执行完。
-
单任务-并行,线上业务的串行单任务场景并不多,大部分是并行任务。比如你想要同时在 minion-01,minion-02,minion-03 三台主机上执行任务,那么并行的单任务就比较合适了。
-
组任务-串行,有时候业务的任务并不是简单的执行一行命令或者是一个脚本,而是很复杂的一个过程。拿我们 mysql 的实例创建来说,它需要初始化主,初始化从,申请 lvs,初始化 failover 等等一系列的子任务,那么业务可以把整个 mysql 实例的创建包装成一个组任务,把其中的每个步骤当成一个子任务。整个组任务是串行执行的,只有当上一个子任务执行成功后,才执行下一个子任务,如果子任务执行失败,组任务就会终止。
-
主机的执行状态,不管是什么任务类型,最终都会落在 minion 主机上去执行,任务刚创建时,minion 处理等待执行的状态,master 收到任务请求后,会通知 minion 执行任务,并通知 qcmd-http 将 minion 的状态标记为处理中,minion 执行完后,将执行结果返回给 master ,master 再通知 qcmd-http 将 minion 的状态标记为成功或者失败。
-
单任务的状态,单任务的状态是根据该任务下的 minion 的状态和单任务的类型来更新的,分为等待处理,处理中,成功,失败和超时等几个状态。
-
组任务的状态,组任务的状态是根据其子任务的状态来更新的,组任务分为等待处理,处理中,成功,失败和超时等几个状态。