前面讲了从数据采集到可视化的五个环节,这些环节有机的组织起来,需要两个关键组件:元数据和调度器。我为了让元数据和元朝对应起来,就把调度器先拿出来讲。大家最早去系统学习调度器,应该是在操作系统课程上,有专门的一章讲调度器的原理,其中花了大量的篇幅讲几种调度算法,但操作系统是如何实现一个调度器,并没有详细讲解。我个人对其都非常困惑,在三年之前,我重新研究操作系统是如何实现时,才把这个问题给解开了,有兴趣的可以看我2012年写的这篇文章《》。操作系统有一个调度器的目的是为了优化硬件资源的利用,当然,操作系统最开始的目的就是为了管理硬件资源的。我们在使用Mysql或者响应一个百度搜索查询时,并不会有一个调度器。那在大数据分析系统中,为何会有一个调度器呢我来回顾一下我在从事大数据工作这几年所实现的几个调度器。
Crontab时代
首先回到2008年那个洪荒年代。我前面提过那个时候我们部门有20台日志统计服务器。每台机器每天会例行跑几十个统计脚本。这些脚本是怎么定时跑起来呢是用一个叫crontab的系统应用。它的功能是指定的时间(精确到分钟)运行某个任务,就像个闹钟。
那我们没有它行不行我们确定每天凌晨00:00,去把所有的统计脚本都跑起来。这里带来的第一个问题就是这些脚本会抢占CPU、内存和IO资源,可能把机器跑死,并且大家可能都跑的很慢。那我们就需要控制个先后顺序,比如每个小时启动一批,把优先级高的先跑(比如给老板看的统计任务)。
还有任务之间有依赖关系的,比如某个任务的输入依赖于其他任务的输出,那就必须后跑了。crontab作为一个定时器是没啥问题的,但管理依赖关系,就闲得力不从心了。那个时候会出现复杂的任务依赖关系,比如3:00的任务依赖与1:00的任务,可1:00的任务由于某种异常出错了,3:00的任务还是定时跑起来了,那结果显然是不对的,并且浪费了计算资源。第二天运维同学恢复了1:00的任务,还要把所有的下游恢复起来,这就很复杂了。让运维同学痛苦的往往就是这种错综复杂的事情,在我们设计日志统计平台时,自然就觉得要有个调度器,而不是继续用crontab来管理任务。
(图1 初版LSP平台架构图)
Scheduler 1.0
我在《盘古开天地》中,对日志统计平台的架构进行了讲解,对调度器Scheduler并没有详细说明。这里先讲讲基本实现:任务可以分为定时任务和有依赖源的任务,这些基本信息都存在数据库任务表中,调度器不断轮询这个表。对于定时任务,一旦发现达到某个时间,就把对应的定时任务运行起来。对于有依赖源的任务,就判断依赖源的就绪状态,比如某份日志是否下载完毕,或者某个其他任务的输出结果是否产生。这些前置条件都满足了,就把对应的任务启动起来。为了防止调度器负荷过重,我们把实际任务的提交和状态获取交给执行器Executor来完成。在上图中的CWrapper就是Executor的一部分。这样的一个好处是可以并发处理多个任务,又保证Scheduler这个单点负荷很轻。
在有许多任务都已就绪时,调度器就按照优先级和任务并发量的限制,给任务排个先后顺序跑。其实任务的优先级制定,也是个麻烦的事情。因为整个平台是给多个业务线使用的,我们怎么判断谁的任务应该先跑我们把任务分成10级,对于反馈到线上的任务,我们把优先级设为最高。其次是给高层看的统计报表。再次是业务线内部的。我们给业务线开了几级的调整权,但大家为了让自己的任务最先跑,都是把任务设置成能设的最高优先级。而我们作为平台方,许多时候是没办法判断不同的业务线到底是谁的更重要的。这个问题一直困扰着我。我们曾经在邮件发出的报表上添加确认阅读链接,对于那些没有被点击的,我们认为没什么人看,就把优先级降低,但很粗糙。在2014年的时候,我曾经安排做了一个计费系统,就是把每个任务提交者所耗费的资源折算成钱,直接显示在平台上,打算尝试去和不同业务线做结算,虽然在我离职前还没有彻底推广开,但我相信是一个不错的思路。
Long Scheduler 1.0
在2012年初,我们重新以数据为中心的思路做用户数据仓库。发现之前日志统计平台的调度器是无法被复用的,和系统的其他部分耦合的太紧。于是就想重新设计一个通用的调度器。因为是龙年,团队同学给起名叫Long Scheduler(简称LS 1.0),不知道的同学都还以为是“长”调度器。这个项目可以说是我做过的比较失败的一个项目。本来是要用于已有日志统计平台和新的用户数据仓库项目的。结果因为地域的原因,用户数据仓库项目组自己搞了一个临时的调度器以保证项目进度。而已有日志统计平台切换到新调度器是一件除了切换本身,没有额外效益的事情,于是优先级并不是很高。还有个问题是设计时依旧是基于日志统计平台做的抽象,还是把平台的一些业务逻辑给带到了里面,导致其他部门的其他系统想要用它来做调度,但发现通用性不够而放弃。最后LS 1.0只用在了新的日志处理平台(Biglog)上。
Long Scheduler 2.0
转眼到了2014年初,我在思考如何将日志处理平台应用在最广的范围上,其中一个思路就是让目前不在平台上的业务部门的任务,也能够用一个通用的调度器给管理起来,这样我们就能够从更大范围优化资源利用。过完春节后,我就把调度器团队的7~8个人召集起来(他们也在承担其他平台建设和维护的工作),要做一个可靠、易用的调度器。之前也做了需求文档和系统设计,但我觉得按照瀑布式的开发流程,很难保证做出来的不是一个半吊子的产品。在我的理念里,优秀的产品一定要是足够流畅的,用户用起来“不卡壳”。
不卡壳有两个层面:一是用户操作时,要感觉很流畅,如果点击一个页面,需要几分钟打开,那就谈不上流畅了。对于互联网产品,这是显而易见的。可对于一些内部MIS系统,就显得似乎没有必要了,甚至觉得优化用户体验是多此一举的。在这里,我不想去探讨,为什么要做这么流畅,你可以先考虑流畅至少没有坏处。
二是不要让用户无所适从。许多工程师会觉得只要有人用,就要把这个功能放到桌子上,这是不对的。只要你摆在那里,用户就需要思考它是干什么的,要不要去操作它。而这样的地方多的时候,就需要有帮助文档。而工程师写的帮助文档往往又不够简洁,于是用户一般都不愿意去看帮助。不要觉得这是用户的问题,因为用户体验不好,完全可以放弃你的产品,那你的系统再牛逼,也是没有价值的。所以在这个项目里,任务的优先级的判断标准是当前最需要的,如果不需要,那就先不做。
这一理念是我颇感自豪的一种能力,在设计Sensors Analytics时,我依旧是按照这种理念把控产品的。
为了实现“不卡壳”,我提了一个大胆的目标:每天都有新Feature发布。通过任务分解、站会、持续集成环境、早期试用等手段,在22个工作日里发布了84个Feature。至于具体如何运作,我就不在这里多讲了,有兴趣的可以看我这篇文章《》。总之经过一个月,实现了一个包括Web界面任务管理、Client任务提交、Service三种任务管理方式的通用调度器。下面是最初的任务配置界面:
(图2 LS 2.0任务配置)
除了前面提交的提交方式的通用,在任务管理方面,采用DAG(有向无环图)的方式管理任务依赖关系,调度器本身做到调度本身所产生的时间延迟在100ms以内。我可以自豪的说我们当时做的调度器应该是最好用的分布式任务调度器了。
开源方案
对于一般创业公司来说,自己开发一个复杂的调度器不太划算,可以选择开源方案。目前比较有名的有和Azkaban。从功能上,Azkaban和LS 2.0是比较接近的,但在2014年初,LS 2.0的界面友好性上要比Azkaban友好的多。Oozie本身不支持可视化任务配置,但开源工具Hue上实现了对任务编辑和运行状态监控的可视化支持,我简单试用了一下,太粗略了。这两个调度器我本人并没有实际用过,有用过的同学,可以和我探讨一下使用的感受。
最后,总结一下调度器的核心功能:一是定时器;二是优化资源利用,特别是任务优先级的控制;三是管理任务依赖关系。
本文为专栏文章,来自:桑文锋,内容观点不代表本站立场,如若转载请联系专栏作者,本文链接:https://www.afenxi.com/9773.html 。