大数据平台架构图那个专业

>>大数据平台架构师
大数据平台架构师
职位描述:
1、负责大数据平台的架构设计,定义可扩展的、分布式的大数据实时计算架构2、负责核心模块研发,完成大数据平台的搭建、系统调试、集成与实施3、负责建立和维护大数据平台技术标准规范,指导开发人员编写代码,根据项目要求编写相关技术文档4、配合产品经理与项目经理规划设计与实施大数据应用
应聘要求:
1、本科及以上计算机、数学相关专业毕业,具有5年以上相关工作经验2、熟练使用开源搜索工具ElasticSearch、Solr或Lucence, 熟悉其原理和源代码,能做比较深入的二次开发3、负责并成功实施过TB级大数据平台建设项目,具备大数据平台性能分析、debug、排障能力4、熟悉Hadoop开发、熟悉Hadoop集群的搭建、管理及优化5、熟悉YARN、Hive、Hbase、Spark、Kafka、Storm、Redis、ZooKeeper等技术,至少精通其中三项以上
申请加入:请将相关简历及应聘岗位邮件到
免费订阅艾瑞每日邮件
微信公众号查看: 8442|回复: 6
现在主流开源分布式系统架构都有哪些?
论坛徽章:0
现在主流开源分布式系统架构都有哪些?
论坛徽章:0
我的 gmail 里面现在还有一封草稿,是发给 erlang-china 社区的。内容是我一直想不明白,为什么 hadoop 成了主流的分布式计算架构,而不是 Erlang/OTP。后来觉得这种比较贴太多了,所以没有发出去。
我认为 Erlang/OTP 系统是最优秀的分布式架构。它的每个特性----变量不变、轻量线程、IPC/RPC 机制、闭包、代码热升级、监控树模型、world等等等等----都是为了分布与并发准备的。用 Erlang 做分布式架构实在太轻松了,开发效率是 C++ 开发的近十倍。
国内很多项目也纷纷让 Erlang 上马,但基本上都秘而不宣。Erlang 社区也曾经一度活跃,到现在,已经沉寂了快两年了。我也很期待像某人解释的那样,兴起必然伴随着跌宕起伏,金子迟早会发光的。
论坛徽章:0
嗯,erlang确实被忽略了!现在多核超线程是该产生点变革性的东东了
论坛徽章:0
scala+akka
论坛徽章:0
粗略一看二郎的语法,顿时奔溃了
能流行起来的东西,往往是因为他简单易用
论坛徽章:0
阅读此文:
Web分布式高性能系统架构剖析
摘要:本文作者Kate Matsudaira是一位美丽的女工程副总裁,曾在Sun Microsystems、微软、亚马逊这些一流的IT公司任职。她有着非常丰富的工作经验和团队管理经验,当过程序员、项目经理、产品经理以及人事经理。专注于构建和操作大型Web应用程序/网站,目前她的主要研究方向是SaaS(软件即服务)应用程序和云计算(如大家所说的大数据)。本文是作者在AOSA一书介绍如何构建可扩展的分布式系统里的内容,在此翻译并分享给大家。
论坛徽章:0
参与人数越多的大系统,使用同构技术带来日后维护的难度风险越高,所以现在开源分布式系统基本都是基于公开协议的 MQ 或 RPC 进行组织的。Erlang 作为一个无所不包的平台,用在一个公司 / 团队内部实现系统是可以的,放在外面,优势不如“找不到合适的人”的劣势明显。
itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号:10 广播电视节目制作经营许可证:编号(京)字第1149号大数据平台架构设计说明书_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
大数据平台架构设计说明书
售前技术顾问|
总评分4.3|
浏览量4757599
用知识赚钱
&&大数据分析,大数据发展趋势,Bigdata,大数据行业分析,大数据,大数据咨询,人工智能,大数据应用
试读已结束,如果需要继续阅读或下载,敬请购买
定制HR最喜欢的简历
你可能喜欢
您可以上传图片描述问题
联系电话:
请填写真实有效的信息,以便工作人员联系您,我们为您严格保密。博客访问: 716
博文数量: 1
注册时间:
ITPUB论坛APP
ITPUB论坛APP
APP发帖 享双倍积分
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 大数据
岗位职责:
负责大数据平台架构规划设计、工具软件开发及相关技术团队的管理;
对数据挖掘及应用开发团队提供技术指导、方案规划及模型设计;
参与企业级大数据产品和应用规划。
岗位要求:&
5年以上软件开发经验,3年以上互联网行业的Hadoop平台的搭建与开发经验;
对基于Hadoop的大数据生态体系有深入认识,具备相关产品(Hadoop、Hive、Hbase、Pig等)项目应用研发经验,有MapReduce
程序的实战开发经验;熟悉Linux系统环境和分布式计算系统的工作机制,能熟练掌握相关核心技术的工作机理,要阅读过Hadoop核心代码;
熟悉大规模并行数据库系统(如Teradata、GreenPlum、Vertica等)或熟悉分布式存储和NoSQL数据库技术(如Cassandra,
MongoDB, Redis等)者优先;
熟悉敏捷开发过程和项目管理,负责过5人以上技术团队的项目开发管理者优先;
工作积极主动,具备很强的责任心、团队合作精神、良好的语言表达及沟通交流能力。
薪酬面谈,福利齐全,对大数据和国企有兴趣的童鞋快快看过来,有意者可以@我,或者直接发简历到,谢谢~~
公司介绍:
中国航信是国资委监管企业之中唯一的一家以信息服务为主业的高科技企业,专业从事航空旅游信息服务。所运营的计算机信息系统和网络系统扮演着行业神经中枢的角色,是民航业务生产链条的重要组成部分。公司资产总额119亿元人民币,拥有5000余人的高素质员工队伍。服务范围覆盖300多个国内城市、100多个国际城市,客户包括近30家国内航空公司以及近200家地区及海外航空公司、174个机场、10,000多家机票销售代理商。
阅读(167) | 评论(0) | 转发(0) |
上一篇:没有了
下一篇:没有了
相关热门文章
给主人留下些什么吧!~~
请登录后评论。新技术体系下大数据平台架构演进a year ago27收藏分享举报文章被以下专栏收录努力做最专业的大数据工程技术和挖掘技术的实践者{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&isPending&:false,&contributes&:[{&sourceColumn&:{&lastUpdated&:,&description&:&&,&permission&:&COLUMN_PUBLIC&,&memberId&:22704,&contributePermission&:&COLUMN_PUBLIC&,&translatedCommentPermission&:&all&,&canManage&:true,&intro&:&努力做最专业的大数据工程技术和挖掘技术的实践者&,&urlToken&:&dataeye&,&id&:18330,&imagePath&:&v2-ad.jpg&,&slug&:&dataeye&,&applyReason&:&0&,&name&:&DataEye数据中心&,&title&:&DataEye数据中心&,&url&:&https:\u002F\\u002Fdataeye&,&commentPermission&:&COLUMN_ALL_CAN_COMMENT&,&canPost&:true,&created&:,&state&:&COLUMN_NORMAL&,&followers&:614,&avatar&:{&id&:&v2-ad&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&activateAuthorRequested&:false,&following&:false,&imageUrl&:&https:\u002F\\u002Fv2-ad_l.jpg&,&articlesCount&:30},&state&:&accepted&,&targetPost&:{&titleImage&:&https:\u002F\\u002Fbbf_r.jpg&,&lastUpdated&:,&imagePath&:&bbf.jpg&,&permission&:&ARTICLE_PUBLIC&,&topics&:[08,1989],&summary&:&\u003Cb\u003E1. \u003C\u002Fb\u003E\u003Cb\u003E引言\u003C\u002Fb\u003E 近年,大数据相关应用发展迅猛,大数据技术亦随之快速进化。这些技术以hadoop体系为基础,不断扩展完善其在数据存储,计算和运维方面的能力,形成更强大的组件。随着业务的发展出现瓶颈,新问题的涌现,我们不可避免会去寻找到这些新的组件,测试并…&,&copyPermission&:&ARTICLE_COPYABLE&,&translatedCommentPermission&:&all&,&likes&:0,&origAuthorId&:0,&publishedTime&:&T17:13:16+08:00&,&sourceUrl&:&&,&urlToken&:,&id&:1152100,&withContent&:false,&slug&:,&bigTitleImage&:false,&title&:&新技术体系下大数据平台架构演进&,&url&:&\u002Fp\u002F&,&commentPermission&:&ARTICLE_ALL_CAN_COMMENT&,&snapshotUrl&:&&,&created&:,&comments&:0,&columnId&:18330,&content&:&&,&parentId&:0,&state&:&ARTICLE_PUBLISHED&,&imageUrl&:&https:\u002F\\u002Fbbf_r.jpg&,&author&:{&bio&:&编程+分析&,&isFollowing&:false,&hash&:&cfd46e561eb9714cbb3bc&,&uid&:16,&isOrg&:false,&slug&:&zhanggj&,&isFollowed&:false,&description&:&&,&name&:&张高境&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhanggj&,&avatar&:{&id&:&da8e974dc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&memberId&:22704,&excerptTitle&:&&,&voteType&:&ARTICLE_VOTE_CLEAR&},&id&:431268}],&title&:&新技术体系下大数据平台架构演进&,&author&:&zhanggj&,&content&:&\u003Ch2\u003E\u003Cb\u003E1.
\u003C\u002Fb\u003E\u003Cb\u003E引言\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
近年,大数据相关应用发展迅猛,大数据技术亦随之快速进化。这些技术以hadoop体系为基础,不断扩展完善其在数据存储,计算和运维方面的能力,形成更强大的组件。随着业务的发展出现瓶颈,新问题的涌现,我们不可避免会去寻找到这些新的组件,测试并完善,最终吸纳接收。本文记录DataEye数据平台组随着开源社区的发展,在数据接入,调度器,数据计算,数据存储和运维等方面不断开拓新技术完善自身架构的过程。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E2.
\u003C\u002Fb\u003E\u003Cb\u003E数据接入\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
接入系统是大数据平台的最基础的部分,同时也是最关键的部分。大数据平台解决的两大问题--存储和计算都是针对数据的操作,所以数据的接入尤其重要。\u003C\u002Fp\u003E\u003Cp\u003E传统的数据接入方案都是在数据源安装一个agent负责收集数据,然后把数据汇总到一起,按照不同的业务需求分发到不同的服务器中,一般有批量和实时两大部分。\u003C\u002Fp\u003E\u003Cp\u003E基于以上思想,我们开发了一套自己的数据接入系统。其中有以下特点:\u003C\u002Fp\u003E\u003Cp\u003E1、提供数据缓存功能\u003C\u002Fp\u003E\u003Cp\u003E2、提供nginx作请求分发,充当负载均衡器。\u003C\u002Fp\u003E\u003Cp\u003E3、多台logserver组成集群进行数据入库。\u003C\u002Fp\u003E\u003Cp\u003E我们的不足:\u003C\u002Fp\u003E\u003Cp\u003E1、入库功能比较单一,只能写入HDFS和Kafka中。\u003C\u002Fp\u003E\u003Cp\u003E2、写入HDFS是通过crontab定时执行put操作上传到HDFS中,不能实时写入。\u003C\u002Fp\u003E\u003Cp\u003E3、logserver代码逻辑复杂,存在大量业务代码,不容易维护。\u003C\u002Fp\u003E\u003Cp\u003E基于以上几点,我们需要寻找更好的数据接入系统。\u003C\u002Fp\u003E\u003Cp\u003E目前市面上存在很多数据收集系统,使用比较广泛的有sqoop、logstash、flume。sqoop一般用在从关系型数据库导数据到hdfs中;logstash一般结合elasticsearch和kibana一起使用;而使用最广泛而且功能最强大的是flume。flume是分布式的可靠的可用的系统,高效的从不同数据源收集聚合迁移大量数据到一个集中的数据存储,使用基于事务的数据传递方式来保证事件传递的可靠性。基于以上特性,我们选择flume作为新的数据接入系统。\u003C\u002Fp\u003E\u003Cp\u003E我们的接入系统架构图如下:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fcf633bb7_b.jpg\& data-rawwidth=\&530\& data-rawheight=\&282\& class=\&origin_image zh-lightbox-thumb\& width=\&530\& data-original=\&https:\u002F\\u002Fcf633bb7_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='530'%20height='282'&&\u002Fsvg&\& data-rawwidth=\&530\& data-rawheight=\&282\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&530\& data-original=\&https:\u002F\\u002Fcf633bb7_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fcf633bb7_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cp\u003E我们采用flume同时入库到多个存储组件中,提供给计算层作为数据源。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E3.
\u003C\u002Fb\u003E\u003Cb\u003E调度器\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
任务调度系统是大数据计算里非常重要的组件。为了实现一次完整的计算,通常需要编写多个MR任务,然后协调这些任务执行的先后顺序,直到所有任务都执行完成,才能得到最终的结果。\u003C\u002Fp\u003E\u003Cp\u003E基于这种思想,我们实现了一套纯Java编写的调度系统,其调度的核心在于:给每个任务都设定一个固定的执行时间点,到达这个时间点后,该任务会检查指定目录是否有上一个任务计算完成的标识文件(如done文件),如果存在,则立即执行,否则就计算下一次调度的时间,重复以上过程。在我们的调度系统中,有以下特点:\u003C\u002Fp\u003E\u003Cp\u003E1、配置任务只需要编写Maper和Reducer模块即可,不需要编写提交类\u003C\u002Fp\u003E\u003Cp\u003E2、可以重复执行和强制重复执行指定的任务\u003C\u002Fp\u003E\u003Cp\u003E3、可以针对特定节点修改参数后再提交执行\u003C\u002Fp\u003E\u003Cp\u003E4、支持cron表达式\u003C\u002Fp\u003E\u003Cp\u003E但是缺点也是相当明显的\u003C\u002Fp\u003E\u003Cp\u003E1、界面简陋\u003C\u002Fp\u003E\u003Cp\u003E2、调度功能单一,不能实现上一个节点执行完成后,下一个立即执行,而是需要等到触发的时间点\u003C\u002Fp\u003E\u003Cp\u003E3、没有任务流的可视化界面\u003C\u002Fp\u003E\u003Cp\u003E4、只能调度MR和HIVE任务\u003C\u002Fp\u003E\u003Cp\u003E为了支持更大规模的任务流调度,我们需要采用一套成熟的任务调度系统。目前市面上\u003C\u002Fp\u003E\u003Cp\u003E存在的调度系统主要有Oozie、Airflow和Azkaban。其中知名度比较高的应该是Apache\nOozie,但是其配置工作流的过程是编写大量的XML配置,而且代码复杂度比较高,不易于二次开发。另外一个应用也比较广泛的调度系统是Airflow,但是其开发语言是Python。由于我们团队内部使用Java作为主流开发语言,所以选型的时候就被淘汰掉了。我们选择Azkaban的原因基于以下几点:\u003C\u002Fp\u003E\u003Cp\u003E1、提供功能清晰,简单易用的Web UI界面\u003C\u002Fp\u003E\u003Cp\u003E2、提供job配置文件快速建立任务和任务之间的依赖关系\u003C\u002Fp\u003E\u003Cp\u003E3、提供模块化和可插拔的插件机制,原生支持command、Java、Hive、Pig、Hadoop\u003C\u002Fp\u003E\u003Cp\u003E4、基于Java开发,代码结构清晰,易于二次开发\u003C\u002Fp\u003E\u003Cp\u003EAzkaban的组成如下:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fde5963cea9_b.jpg\& data-rawwidth=\&508\& data-rawheight=\&219\& class=\&origin_image zh-lightbox-thumb\& width=\&508\& data-original=\&https:\u002F\\u002Fde5963cea9_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='508'%20height='219'&&\u002Fsvg&\& data-rawwidth=\&508\& data-rawheight=\&219\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&508\& data-original=\&https:\u002F\\u002Fde5963cea9_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fde5963cea9_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E由上图可知Azkaban的系统结构相当简单,Web\nServer提供前端访问的web界面和接收HTTP请求,Executor Server负责执行相应的任务,MySQL则是用来保存元数据信息。\u003C\u002Fp\u003E\u003Cp\u003E但是Azkaban也有一些不足的地方:\u003C\u002Fp\u003E\u003Cp\u003E1、任务不能基于实例重跑\u003C\u002Fp\u003E\u003Cp\u003E2、不支持cron表达式\u003C\u002Fp\u003E\u003Cp\u003E3、需要编写主类来执行MR任务\u003C\u002Fp\u003E\u003Cp\u003E4、只能基于邮件告警\u003C\u002Fp\u003E\u003Cp\u003E我们团队对Azkaban做了大量的二次开发,吸收了我们老的调度器里的优点,也扩展了Azkaban原有的功能。具体改造情况如下:\u003C\u002Fp\u003E\u003Cp\u003E1、由原来简单按时间步长来调度任务,修改为支持cron表达式\u003C\u002Fp\u003E\u003Cp\u003E2、由原来的邮件告警,修改为支持本公司的告警系统\u003C\u002Fp\u003E\u003Cp\u003E3、添加重复执行实例的功能\u003C\u002Fp\u003E\u003Cp\u003E4、支持把指定日期字符串解析为路径\u003C\u002Fp\u003E\u003Cp\u003E5、MR代码提交方式的改造,不再需要编写主类,通过配置的方式即可提交任务\u003C\u002Fp\u003E\u003Cp\u003E通过以上改造后,Azkaban在保持原有功能的同时,也兼容了老调度器的优点。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E4.
\u003C\u002Fb\u003E\u003Cb\u003E数据计算\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
Dataeye的计算平台分为实时计算和离线计算两部分:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002F48a4f3a69c37a9b7e173b04e439a5afd_b.jpg\& data-rawwidth=\&554\& data-rawheight=\&246\& class=\&origin_image zh-lightbox-thumb\& width=\&554\& data-original=\&https:\u002F\\u002F48a4f3a69c37a9b7e173b04e439a5afd_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='554'%20height='246'&&\u002Fsvg&\& data-rawwidth=\&554\& data-rawheight=\&246\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&554\& data-original=\&https:\u002F\\u002F48a4f3a69c37a9b7e173b04e439a5afd_r.jpg\& data-actualsrc=\&https:\u002F\\u002F48a4f3a69c37a9b7e173b04e439a5afd_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E
数据从接入系统进入kafka集群后,将分别进入实时处理的jstorm集群和离线处理的yarn\u002Fhdfs集群。\u003C\u002Fp\u003E\u003Cp\u003E对于实时处理我们需要高稳定性和响应速度,我们选择了单独搭建jstorm集群来满足我们实时处理的需求。一方面,单独的jstorm集群更便于维护,减少了因为资源争用而造成的影响实时系统稳定性的问题;另一方面,jstorm也支持我们做任何时间粒度实时计算的需求。\u003C\u002Fp\u003E\u003Cp\u003E对于离线计算平台,我们选择了yarn和hdfs,我们在yarn之上构建支持了不同数据计算引擎,包括spark、map-reduce和用于OLAP的kylin,通过组合这些不同的计算引擎来满足我们各方面数据处理的需求。\u003C\u002Fp\u003E\u003Cp\u003E通过yarn的资源抽象和管理能力,我们很容易的实现在一套集群上根据不同的需要选择不同计算引擎的功能,且目前的数据处理框架一般对yarn的支持也比较完善,所以我们没有选择单独搭建其他计算资源共享系统。在yarn中我们主要使用yarn的资源队列、tag和弹性调度的功能来实现多租户、多计算引擎的支持。例如,可以通过结合yarn的tag功能我们可以把spark任务尽可能的调度到我们大内存机器上。通过yarn我们也大大提高了我们集群资源的使用效率。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E5.
\u003C\u002Fb\u003E\u003Cb\u003E数据存储\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003E传统解决方案\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
业务上线初期,数据量通常较小,此时的应用,无论是侧重OLTP还是OLAP,关系数据库,如MYSQL都是很好的选择。\u003C\u002Fp\u003E\u003Cp\u003E
但随着业务的扩展,数据变化的多样性及海量增长,MySql的可扩展能力及分析能力已显得捉襟见肘,引入分布式存储系统迫在眉睫。\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003E分布式存储系统要求\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
针对数据应用场景的不同以及数据组织的多样性,如基于键值(Key-Value)的,有基于文档(Document),还有基于列(Column)和图表(Graph)的,如果采用单一的数据库引擎,“一刀切式”的满足所有类型的数据存储需求,通常会严重降低数据库管理的性能。因此,需要引入多元的数据存储解决方案。\u003C\u002Fp\u003E\u003Cp\u003E
下面介绍数据平台几种存储系统(存储引擎)的引入。\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003EHive\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
Hive是一个典型的SQL on Hadoop的应用,Hive可以用传统的SQL 读写和管理一个大规模的数据仓库。由于其构建在HDFS之上,所以它继承了HDFS的高可扩展性、高可用性和安全性。Hive将SQL转化成一系列的MapReduce任务,执行后得到结果,大大减轻了数据分析人员的负担,但也是由于其使用MapReduce作为计算引擎,所以数据访问延迟较大,依然只适用离线分析的应用场景。在Hive即将发行的版本中,将集成Spark、Tez等计算引擎。这将大大降低在超大规模的数据仓库上的数据分析时延。\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002F249d87b5bec929c9c3a167448fcf8207_b.jpg\& data-rawwidth=\&554\& data-rawheight=\&501\& class=\&origin_image zh-lightbox-thumb\& width=\&554\& data-original=\&https:\u002F\\u002F249d87b5bec929c9c3a167448fcf8207_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='554'%20height='501'&&\u002Fsvg&\& data-rawwidth=\&554\& data-rawheight=\&501\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&554\& data-original=\&https:\u002F\\u002F249d87b5bec929c9c3a167448fcf8207_r.jpg\& data-actualsrc=\&https:\u002F\\u002F249d87b5bec929c9c3a167448fcf8207_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003EImpala\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
Impala是另一个SQL on Hadoop的应用。它的引入就是为了弥补Hive的不足,与Hive不同的是,它是一个可用于实时应用场景的系统。它避开了MapReduce计算引擎,采用了类似于商业的关系型数据库中的并行计算引擎。因为查询效率是Hive的多个数量级(order-of-magnitude)。与Hive类似,它同时支持一些面向行或者列的文件存储格式,如:Text,RCFile,\nParquet, ORCFile等。\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002F30c01f6f22a898f2e4523f4ccc99ab42_b.jpg\& data-rawwidth=\&554\& data-rawheight=\&327\& class=\&origin_image zh-lightbox-thumb\& width=\&554\& data-original=\&https:\u002F\\u002F30c01f6f22a898f2e4523f4ccc99ab42_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='554'%20height='327'&&\u002Fsvg&\& data-rawwidth=\&554\& data-rawheight=\&327\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&554\& data-original=\&https:\u002F\\u002F30c01f6f22a898f2e4523f4ccc99ab42_r.jpg\& data-actualsrc=\&https:\u002F\\u002F30c01f6f22a898f2e4523f4ccc99ab42_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003EHbase\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
Hbase是一个分布式的、面向列的开源数据库。其设计理念源自谷歌的BigTable。在实时业务中,数据被送到Storm实时流引擎计算后,暂存于Redis集群;由于这些数据体量较大,指标通常较多(表宽,列多),结构也具有不确定性,所以常常用Hbase来存储,用于实时读写。\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003EApache Kylin\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
在数据平台的部分业务中,存在一种需求:用户通常需要关联查询,多个表的多个维度的汇总数据,这是一种典型的OLAP场景。Hive和Impala,固然能解决这种问题,然而Hive 的时延太高;impala对于单表查询或者少量维度的连接查询,性能尚可,但对于多个维度、大体量的表上显得心余力绌。然而,Apache Kylin正是解决这种问题的利刃。\u003C\u002Fp\u003E\u003Cp\u003E
Apache Kylin 是一个 实时(real-time)的OLAP on\nHadoop的应用。\n它可以通过ANSI-SQL,ODBC, JDBC,RESTful API等接口,提供基于hadoop的超大数据集(TB-PB级)的多维实时分析(OLAP)功能。\u003C\u002Fp\u003E\u003Cp\u003E
Apache Kylin以Hive数据仓库为数据源,针对一个星型拓扑结构的\u003Cb\u003E数据立方体\u003C\u002Fb\u003E,预计算多个\u003Cb\u003E维度\u003C\u002Fb\u003E组合的\u003Cb\u003E度量\u003C\u002Fb\u003E,然后将结果保存在Hbase中,对外提供查询分析功能。\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002F82fc635bab19c_b.jpg\& data-rawwidth=\&554\& data-rawheight=\&358\& class=\&origin_image zh-lightbox-thumb\& width=\&554\& data-original=\&https:\u002F\\u002F82fc635bab19c_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='554'%20height='358'&&\u002Fsvg&\& data-rawwidth=\&554\& data-rawheight=\&358\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&554\& data-original=\&https:\u002F\\u002F82fc635bab19c_r.jpg\& data-actualsrc=\&https:\u002F\\u002F82fc635bab19c_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003ETITAN\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cp\u003E
对于图(Graph)结构的数据和计算,我们引入TITAN. TITAN是一个分布式的图数据库,它可以存储具有上千亿级别顶点(vertice )和边(edge)的图结构在分布式集群中。另外TITAN是一个事务性的数据库,可支持数千个用户并发、实时地遍历图结构。\u003C\u002Fp\u003E\u003Cp\u003E
各种大数据处理技术存在能力互补,按照大数据处理技术能力互补原则,兼顾高效与低成本,结合当前技术发展状态,业务应用场景等,采用多技术混搭方式实现大数据平台的存储。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E6.
\u003C\u002Fb\u003E\u003Cb\u003E运维系统\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
Dataeye的大数据运维平台由以下几个部分组成:部署和配置管理系统,平台各项metric采集、监控和告警系统,以及任务的自动化分析和优化框架。整个运维平台的建设的思路就是:自动化和灵活配置。\u003C\u002Fp\u003E\u003Cp\u003E
首先在平时的运维过程中会涉及到许多部署基础软件和变更配置信息的工作,在平台建设的初期,机器比较少,可能通过人工去部署和维护所有机器的配置信息也可以搞定,但随着集群的快速发展,人工的方式越来越吃力和缺乏可维护性。在Dataeye我们通过fabric加上git来完成集群的部署和配置信息维护。在众多的DevOps工具中我们选择了fabric,主要是看中其简单、灵活和依赖较少的特点。在fabric的基础上我们封装了一套基础的接口,这些接口以合适的粒度包装了常用的部署操作(例如安装一个软件包,执行基础环境检查,更新配置信息等等),然后通过组装这些接口,我们可以很灵活的定义部署任务。对于集群的配置文件管理我们采用git进行版本化管理,所有配置信息放在主干上版本化,对于某些机器需要特殊配置的(例如内存配置不同,磁盘有临时坏盘)采用分支管理,更新集群的配置信息时只需要根据主干和分支配置对不同机器进行更新即可,解决了配置管理的问题。\u003C\u002Fp\u003E\u003Cp\u003E
对于集群和任务执行的状态进行监控,我们结合开源项目和内部平台,构建了一套完整的集指标采集、展示和监控告警为一体的系统。在指标采集方面充分利用各个基础系统Metric数据,对于Metric指标中没有的监控数据,我们采用logstash进行采集;对于采集的数据一方面写入ganglia中进行展示,另一方面数据也会导入我们自己构建的监控告警系统,进行数据指标的监控和告警。对于任务的执行情况我们通过任务调度器azkaban的sal进行监控。\u003C\u002Fp\u003E\u003Cp\u003E
每天整个数据平台会运行非常多个各种任务,包括map-reduce、hive和spark等,一般情况下我们会通过yarn或者spark自身提供的web页面去观察任务的执行情况。对于任务的分析和优化,一方面只有在页面上观察和反映出问题的时候才去进行,这种方式比较被动和耗费精力;另一方面解决问题所使用的优化策略,也很难同步到所有的人。所以,我们希望任务的分析和性能优化这方面的工作尽可能做到自动化,并做到可以不断积累优化经验,使得分析和优化工作更加智能化。基于这种想法,我们使用了并改造了开源项目dr-elephant来自动化进行任务的分析和优化。dr-elephant通过我们自定义的启发式优化规则来分析任务的执行的history的数据,如果任务的分析结果触发了某些启发规则,系统会给出优化提示。例如,如果任务处理大量的小文件,系统会提示进行文件合并或者采用CombineInputFormat格式,或者spark任务参数设置不合理等,并且这些启发式规则可以不断扩充,通过dr-elephant我们自动化了任务的分析和性能优化,使得整个数据平台的运行效率大大提高。\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fe874f5ff3bf8ccbdbada76_b.jpg\& data-rawwidth=\&558\& data-rawheight=\&378\& class=\&origin_image zh-lightbox-thumb\& width=\&558\& data-original=\&https:\u002F\\u002Fe874f5ff3bf8ccbdbada76_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='558'%20height='378'&&\u002Fsvg&\& data-rawwidth=\&558\& data-rawheight=\&378\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&558\& data-original=\&https:\u002F\\u002Fe874f5ff3bf8ccbdbada76_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fe874f5ff3bf8ccbdbada76_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E7.
\u003C\u002Fb\u003E\u003Cb\u003E总结\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E
在各家工具都在标榜自身产品功能有多强大,性能有优越时,带给开发者的难题其实是选择上的困难。在我们看来不管是哪种产品在现实使用时往往只能解决一类问题,并不存在大一统的工具,例如在OLAP领域,我们需要权衡即席查询的数据量,响应速度,维度,复杂度以及灵活性等多个方面的问题,最终得出的结论是必须多个工具一起上才能解决问题。\u003C\u002Fp\u003E\u003Cp\u003E
工具的多样性给后期平台整体稳定运行带来很大挑战,为此,DE数平组的同事在工具选型,稳定性及性能测试时极为慎重,一个工具正式上线运营往往需要几个月反复测试,同时我们会积极探索平台的自运维能力,如采用启发式的规则主动发现系统问题,这些在实际运维中都起到了非常好的效果。在经过不断试错创新之后,我们最终期望的是能构建一个功能强大,能长期稳定运行且具有自运维能力的数据平台。\u003C\u002Fp\u003E&,&updated&:new Date(&T09:13:16.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:4,&collapsedCount&:0,&likeCount&:27,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&titleImage&:&https:\u002F\\u002Fbbf_r.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&reviewers&:[],&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&大数据处理&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&大数据&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&架构&}],&adminClosedComment&:false,&titleImageSize&:{&width&:1920,&height&:832},&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&column&:{&slug&:&dataeye&,&name&:&DataEye数据中心&},&tipjarState&:&inactivated&,&annotationAction&:[],&sourceUrl&:&&,&pageCommentsCount&:4,&hasPublishingDraft&:false,&snapshotUrl&:&&,&publishedTime&:&T17:13:16+08:00&,&url&:&\u002Fp\u002F&,&lastestLikers&:[{&bio&:&重新追逐生活的意义&,&isFollowing&:false,&hash&:&&,&uid&:314300,&isOrg&:false,&slug&:&yin-shuai-74-31&,&isFollowed&:false,&description&:&&,&name&:&逐梦&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyin-shuai-74-31&,&avatar&:{&id&:&adcb25dc575&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&VC Lv.1&,&isFollowing&:false,&hash&:&a5fbd650a3&,&uid&:00,&isOrg&:false,&slug&:&yuan-xiao-bai-22&,&isFollowed&:false,&description&:&人生如戏&,&name&:&原小白&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyuan-xiao-bai-22&,&avatar&:{&id&:&c5d150f8a8f3ed4ce2e913fc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&多年大数据研发管理及丰富的行业经验,写过代码做过架构出过产品。&,&isFollowing&:false,&hash&:&0e24a325a92546baab18f3eb&,&uid&:52,&isOrg&:false,&slug&:&decli&,&isFollowed&:false,&description&:&http:\u002F\u002Fmy.oschina.net\u002Fleejun2005&,&name&:&dec li&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fdecli&,&avatar&:{&id&:&ab212099f&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:null,&isFollowing&:false,&hash&:&ecc16d428ad351a6ea45917eae29aebc&,&uid&:72,&isOrg&:false,&slug&:&he-zu-89&,&isFollowed&:false,&description&:&&,&name&:&何族&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fhe-zu-89&,&avatar&:{&id&:&6c21d18fe24c93a9ffaf73&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&不要邀我回答问题&,&isFollowing&:false,&hash&:&fbd9bed2e7e6db096bdfb276&,&uid&:88,&isOrg&:false,&slug&:&duuuuuck&,&isFollowed&:false,&description&:&格物致知,明心见性&,&name&:&summer&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fduuuuuck&,&avatar&:{&id&:&22d61b29fff02a0ff45e4&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}],&summary&:&\u003Cimg src=\&https:\u002F\\u002Fcf633bb7_200x112.jpg\& data-rawwidth=\&530\& data-rawheight=\&282\& class=\&origin_image inline-img zh-lightbox-thumb\& data-original=\&https:\u002F\\u002Fcf633bb7_r.jpg\&\u003E\u003Cb\u003E1. \u003C\u002Fb\u003E\u003Cb\u003E引言\u003C\u002Fb\u003E 近年,大数据相关应用发展迅猛,大数据技术亦随之快速进化。这些技术以hadoop体系为基础,不断扩展完善其在数据存储,计算和运维方面的能力,形成更强大的组件。随着业务的发展出现瓶颈,新问题的涌现,我们不可避免会去寻找到这些新的组件,测试并…&,&reviewingCommentsCount&:0,&meta&:{&previous&:{&isTitleImageFullScreen&:false,&rating&:&none&,&titleImage&:&https:\u002F\\u002F50\u002F7f234c710e88edc9d58e7a3e4956634e_xl.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&Hadoop&}],&adminClosedComment&:false,&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&author&:{&bio&:&人生喜欢跟人生观开玩笑。&,&isFollowing&:false,&hash&:&9ef31e8b062d0f6cba952d&,&uid&:48,&isOrg&:false,&slug&:&ou-yang-jie-90&,&isFollowed&:false,&description&:&人生喜欢跟人生观开玩笑。&,&name&:&彭小漪&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fou-yang-jie-90&,&avatar&:{&id&:&v2-dbc96ce10db1f9caa4e6fc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&column&:{&slug&:&dataeye&,&name&:&DataEye数据中心&},&content&:&作业(job)提交时,会被map-reduce 框架的JobTracker 拆成一系列的map任务、reduce任务在整个hadoop 集群的机器上执行。\u003Cp\u003E由于一些原因,比如硬件老化,软件层面的不恰当配置等。某些机器上的任务实例 执行很慢,拖累了整个作业(job)的进度;hadoop不会尝试去诊断或者修复这些慢任务,相反,它会在集群的其他节点上去启动这些慢任务的多个实例作为备份,这就是hadoop的推测执行(\u003Cb\u003Especulative execution\u003C\u002Fb\u003E)。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E比如,hadoop集群中的有一台机器M,有一块很慢的磁盘。当一个作业(job)分配在其他机器上的任务都已完成,机器M上的任务进度还不到20%,这样会明显拖累整个job的执行时间。\u003C\u002Fp\u003E\u003Cp\u003E因此在hadoop集群刚建立不久,每台机器的性能差异不太确定;或者hadoop集群中的机器硬件配置差异较大的情况下,开启\u003Cb\u003Especulative execution\u003C\u002Fb\u003E 是很有必要的。\u003C\u002Fp\u003E\u003Cp\u003E若要开启hadoop的 \u003Cb\u003Especulative execution\u003C\u002Fb\u003E,需在mapred-site.xml配置设置以下两个配置项:\u003C\u002Fp\u003E\u003Cp\u003Ehadoop1.x\u003C\u002Fp\u003E\u003Cblockquote\u003E\u003Cul\u003E\u003Cli\u003Emapred.map.tasks.speculative.execution=true\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Emapred.reduce.tasks.speculative.execution=true\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003C\u002Fblockquote\u003Ehadoop2.x\u003Cbr\u003E\u003Cblockquote\u003E\u003Cul\u003E\u003Cli\u003Emapreduce.map.speculative=true\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Emapreduce.reduce.speculative=true\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003C\u002Fblockquote\u003E\u003Cbr\u003E\u003Cp\u003E另外,具体任务实例满足什么条件,JobTracker会分配该任务的其他实例在其他节点上运行?\u003C\u002Fp\u003E\u003Cp\u003E查看代码如下:\u003C\u002Fp\u003E\u003Cblockquote\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-java\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&kt\&\u003Eboolean\u003C\u002Fspan\u003E \u003Cspan class=\&nf\&\u003EhasSpeculativeTask\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&kt\&\u003Elong\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EcurrentTime\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Edouble\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EaverageProgress\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&c1\&\u003E\u002F\u002F\u003C\u002Fspan\u003E\n
\u003Cspan class=\&c1\&\u003E\u002F\u002F REMIND - mjc - these constants should be examined\u003C\u002Fspan\u003E\n
\u003Cspan class=\&c1\&\u003E\u002F\u002F in more depth eventually...\u003C\u002Fspan\u003E\n
\u003Cspan class=\&c1\&\u003E\u002F\u002F\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Eif\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E(!\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eskipping\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&&\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EactiveTasks\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&na\&\u003Esize\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E()\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EMAX_TASK_EXECS\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&o\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EaverageProgress\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E-\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Eprogress\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003ESPECULATIVE_GAP\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&o\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EcurrentTime\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E-\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EstartTime\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003ESPECULATIVE_LAG\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E)\u003C\u002Fspan\u003E \n
\u003Cspan class=\&o\&\u003E&&\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Ecompletes\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E==\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E&&\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E!\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EisOnlyCommitPending\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E())\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Ereturn\u003C\u002Fspan\u003E \u003Cspan class=\&kc\&\u003Etrue\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&o\&\u003E}\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Ereturn\u003C\u002Fspan\u003E \u003Cspan class=\&kc\&\u003Efalse\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&o\&\u003E}\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E\u003Cbr\u003E我们得知,当一个任务正在运行的实例个数小于或等于MAX_TASK_EXECS(1) ,且其进度与所有任务实例的平均进度之差大于SPECULATIVE_GAP(20%)和其开始时间与当前JobTracker的时间之差大于1分钟(60 * 1000ms)时,就会有该任务的其他实例在集群内的其他节点上执行。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E\u003Cb\u003E参考文档:\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\\u002FWhat-is-the-speculative-execution-in-hadoop\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003E[1].https:\u002F\\u002FWhat-is-the-speculative-execution-in-hadoop\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E\u003C\u002Fp\u003E&,&state&:&published&,&sourceUrl&:&&,&pageCommentsCount&:0,&canComment&:false,&snapshotUrl&:&&,&slug&:,&publishedTime&:&T15:36:12+08:00&,&url&:&\u002Fp\u002F&,&title&:&Hadoop map-reduce的 speculative execution(推测执行)&,&summary&:&作业(job)提交时,会被map-reduce 框架的JobTracker 拆成一系列的map任务、reduce任务在整个hadoop 集群的机器上执行。由于一些原因,比如硬件老化,软件层面的不恰当配置等。某些机器上的任务实例 执行很慢,拖累了整个作业(job)的进度;hadoop不会尝…&,&reviewingCommentsCount&:0,&meta&:{&previous&:null,&next&:null},&commentPermission&:&anyone&,&commentsCount&:0,&likesCount&:3},&next&:{&isTitleImageFullScreen&:false,&rating&:&none&,&titleImage&:&https:\u002F\\u002F50\u002F2f83ed15b49c0f7d08eb8_xl.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&任务系统&}],&adminClosedComment&:false,&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&author&:{&bio&:null,&isFollowing&:false,&hash&:&25d4a60955fbea3c4ec2b52&,&uid&:80,&isOrg&:false,&slug&:&wang-yan-hong-84&,&isFollowed&:false,&description&:&&,&name&:&王彦鸿&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fwang-yan-hong-84&,&avatar&:{&id&:&129c2a8c9&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&column&:{&slug&:&dataeye&,&name&:&DataEye数据中心&},&content&:&Azkaban原生的定时器只能支持从指定时间起,按时间步长周期性地调度任务。这种调度方式使用简单,也比较容易理解,但是我们有些任务调度时间是非周期性的,例如只在周六和周日的某个时间点执行,这样原生的定时器就不能支持。为此我们需要改造Azkaban的定时器功能,让其能支持Cron表达式。同时提供调度任务的激活和冻结功能,刚创建的调度任务是不会立即执行的,而是需要点击“Active”按钮才能进入定时执行。\u003Cp\u003E1、界面改造\u003C\u002Fp\u003E\u003Cp\u003E(1)设置定时器界面\u003C\u002Fp\u003E\u003Cp\u003E原生的设置定时器界面如下:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cimg src=\&https:\u002F\\u002Fbb150e66fbe53aa9d40825_b.jpg\& data-rawwidth=\&569\& data-rawheight=\&317\& class=\&origin_image zh-lightbox-thumb\& width=\&569\& data-original=\&https:\u002F\\u002Fbb150e66fbe53aa9d40825_r.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cp\u003E我们需要改造为支持Cron表达式,则以上这些输入框都会无效,所以全部变成隐藏状态。\u003C\u002Fp\u003E\u003Cp\u003E修改 schedulepanel.vm 文件,把 class=\&form-group\& 的三个div设置为 style=\&display:\&\u003C\u002Fp\u003E\u003Cp\u003E添加div,命名为Cron,id为cronpicker\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E&div class=\&form-group\&&\n
&label class=\&col-sm-2 control-label\&&Cron&\u002Flabel&\n
&div class=\&col-sm-10\&&\n
&input type=\&text\& id=\&cronpicker\& class=\&form-control\&&\n
&\u002Fdiv&\n&\u002Fdiv&\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E这样界面效果如下:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cfigure\u003E\u003Cimg src=\&https:\u002F\\u002Ffe3b3b9f47ad6c2f0daa5ce24fff64d7_b.jpg\& data-rawwidth=\&569\& data-rawheight=\&225\& class=\&origin_image zh-lightbox-thumb\& width=\&569\& data-original=\&https:\u002F\\u002Ffe3b3b9f47ad6c2f0daa5ce24fff64d7_r.jpg\&\u003E\u003C\u002Ffigure\u003E(2)调度器列表界面\u003C\u002Fp\u003E\u003Cp\u003E原生的调度器列表界面如下:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cfigure\u003E\u003Cimg src=\&https:\u002F\\u002F7a5a481f2e31e3890feaaf7c40fbe616_b.jpg\& data-rawwidth=\&1241\& data-rawheight=\&82\& class=\&origin_image zh-lightbox-thumb\& width=\&1241\& data-original=\&https:\u002F\\u002F7a5a481f2e31e3890feaaf7c40fbe616_r.jpg\&\u003E\u003C\u002Ffigure\u003E经过以上的改造,Repeats Every 栏就没用了,我们使用Cron表示,另外增加“Active”、“DeActive”功能,任务刚创建的时候是冻结状态的,显示按钮“Active”,当用户点击该按钮后,按钮变成“DeActive”,用于用户把任务由激活状态变为冻结状态。\u003C\u002Fp\u003E\u003Cp\u003E修改scheduledflowpage.vm文件,把“Repeats Every”改为“Cron Expr”,把$utils.formatPeriod(${sched.period}) 改为 ${sched.cronExpr},添加按钮的代码如下\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E&td&\n #if(${sched.status} == \&PAUSED\&)\n
&button type=\&button\& id=\&activeBtn\& class=\&btn btn-sm btn-primary\& onclick=\&activeSched(${sched.scheduleId})\& &Active&\u002Fbutton&\n #else\n
&button type=\&button\& id=\&deActiveBtn\& class=\&btn btn-sm btn-danger\& onclick=\&deActiveSched(${sched.scheduleId})\& &DeActive&\u002Fbutton&\n #end\n&\u002Ftd&\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cbr\u003E\u003Cp\u003E界面效果如下:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cfigure\u003E\u003Cimg src=\&https:\u002F\\u002Fd3b752e3f5aea9aabe90c849f575a456_b.jpg\& data-rawwidth=\&1167\& data-rawheight=\&83\& class=\&origin_image zh-lightbox-thumb\& width=\&1167\& data-original=\&https:\u002F\\u002Fd3b752e3f5aea9aabe90c849f575a456_r.jpg\&\u003E\u003C\u002Ffigure\u003E当然要修改对应的 js 文件,在schedule.js文件添加以下两个函数\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-js\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&kd\&\u003Efunction\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EactiveSched\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleId\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EscheduleURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EcontextURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E+\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&\u002Fschedule\&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EredirectURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EcontextURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E+\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&\u002Fschedule\&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003ErequestData\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&s2\&\u003E\&action\&\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&activeSched\&\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E\n
\u003Cspan class=\&s2\&\u003E\&scheduleId\&\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleId\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EsuccessHandler\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&kd\&\u003Efunction\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Eif\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Eerror\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nx\&\u003E$\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&s1\&\u003E'#errorMsg'\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E).\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Etext\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Eerror\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Eelse\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nb\&\u003Ewindow\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Elocation\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EredirectURL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nx\&\u003E$\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Epost\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleURL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003ErequestData\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EsuccessHandler\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&json\&\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&kd\&\u003Efunction\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EdeActiveSched\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleId\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EscheduleURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EcontextURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E+\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&\u002Fschedule\&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EredirectURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EcontextURL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E+\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&\u002Fschedule\&\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003ErequestData\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&s2\&\u003E\&action\&\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&deactiveSched\&\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E\n
\u003Cspan class=\&s2\&\u003E\&scheduleId\&\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleId\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kd\&\u003Evar\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EsuccessHandler\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&kd\&\u003Efunction\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Eif\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Eerror\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nx\&\u003E$\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&s1\&\u003E'#errorMsg'\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E).\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Etext\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Eerror\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Eelse\u003C\u002Fspan\u003E \u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nb\&\u003Ewindow\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Elocation\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EredirectURL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n
\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n
\u003Cspan class=\&nx\&\u003E$\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003Epost\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&nx\&\u003EscheduleURL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003ErequestData\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&nx\&\u003EsuccessHandler\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&s2\&\u003E\&json\&\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E}\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E2、支持Cron表达式的后台代码\u003C\u002Fp\u003E\u003Cp\u003E需要在工程里导入quartz-2.1.3.jar包,同时部署到线上的时候,需要把该包拷贝到azkaban\u002Flib目录下。\u003C\u002Fp\u003E\u003Cp\u003E在 azkaban-common\u002Fbuild.gradle 和 azkaban-webserver\u002Fbuild.gradle 两个文件下添加quartz的配置:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Ecompile('org.quartz-scheduler:quartz:2.1.3')\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E(1)新增Java类 CronBasedScheduleLoader 实现 ScheduleLoader接口,内容与TriggerBasedScheduleLoader类相同,只需要添加一个方法\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E
private Trigger scheduleToTrigger(Schedule s, TriggerStatus status) {\n
Condition triggerCondition = createTriggerCondition(s);\n
Condition expireCondition = createExpireCondition(s);\n
List&TriggerAction& actions = createActions(s);\n
Trigger t =\n
new Trigger(s.getScheduleId(), s.getLastModifyTime(),\n
s.getSubmitTime(), s.getSubmitUser(), triggerSource,\n
triggerCondition, expireCondition, actions);\n
t.setStatus(status);\n
if (s.isRecurring()) {\n
t.setResetOnTrigger(true);\n
} else {\n
t.setResetOnTrigger(false);\n
}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E然后把BasicTimeChecker_
修改为 CronExprChecker_ \u003C\u002Fp\u003E\u003Cp\u003E(2)新增CronExprChecker类,实现ConditionChecker接口,添加String cronExpr变量,重写以下方法\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Eprivate long calculateNextCheckTime() {\n
DateTime date = new DateTime(nextCheckTime).withZone(timezone);\n
int count = 0;\n
while (!date.isAfterNow()) {\n
if (count & 100000) {\n
throw new IllegalStateException(\&100000 increments of period did not get to present time.\&);\n
if (cronExpr == null) {\\n
} else {\n
CronExpression exp = new CronExpression(cronExpr);\n
Date cronDate = exp.getNextValidTimeAfter(date.toDate());\n
date = new DateTime(cronDate.getTime()).withZone(timezone);\n
}catch (Exception ex){\n
throw new IllegalStateException(\&parse crom error.\&);\n
count += 1;\n
if (!skipPastChecks) {\\n
return date.getMillis();\n
}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E此处就是整个改造的核心点,用到了quartz组件来实现获取下一个执行时间的功能\u003C\u002Fp\u003E\u003Cp\u003E(3)在Schedule类添加private String cronExpr属性,和对应的set\u002Fget方法\u003C\u002Fp\u003E\u003Cp\u003E(4)在AzkabanWebServer类中,把loadScheduleManager改为loadCronScheduleManager,方法如下\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E
private ScheduleManager loadCronScheduleManager(TriggerManager tm, Props props)\n
throws Exception {\n
(\&Loading trigger based scheduler\&);\n
ScheduleLoader loader =\n
new CronBasedScheduleLoader(tm, ScheduleManager.triggerSource);\n
return new ScheduleManager(loader);\n
}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E(5)修改ScheduleServlet,用来获取cronpicker的数据\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E
String cronpicker = getParam(req, \&cronpicker\&);\n
DateTime firstSchedT\n
CronExpression exp = new CronExpression(cronpicker);\n
Date cronDate = exp.getNextValidTimeAfter(new Date());\n
firstSchedTime = new DateTime(cronDate.getTime()).withZone(DateTimeZone.getDefault());\n
} catch (Exception e) {\n
ret.put(\&error\&, \&Invalid date and\u002For time.\&);\\n
}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E3、支持冻结和激活的后台代码\u003C\u002Fp\u003E\u003Cp\u003E修改ScheduleServlet类的代码,在handlePost方法内添加\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Eelse if (action.equals(\&activeSched\&)) {\n
ajaxActiveSched(req, ret, session.getUser());\n} else if (action.equals(\&deactiveSched\&)) {\n
ajaxDeActiveSched(req, ret, session.getUser());\n}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E具体实现如下\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E
private void ajaxActiveSched(HttpServletRequest req, Map&String, Object& ret, User user) throws ServletException {\n
int scheduleId = getIntParam(req, \&scheduleId\&);\n
sched = scheduleManager.getSchedule(scheduleId);\n
} catch (ScheduleManagerException e) {\n
throw new ServletException(e);\n
if (sched == null) {\n
ret.put(\&message\&, \&Schedule with ID \& + scheduleId + \& does not exist\&);\n
ret.put(\&status\&, \&error\&);\\n
Project project = projectManager.getProject(sched.getProjectId());\n\n
if (project == null) {\n
ret.put(\&message\&, \&Project \& + sched.getProjectId() + \& does not exist\&);\n
ret.put(\&status\&, \&error\&);\\n
if (!hasPermission(project, user, Type.SCHEDULE)) {\n
ret.put(\&status\&, \&error\&);\n
ret.put(\&message\&, \&Permission denied. Cannot remove schedule with id \& + scheduleId);\\n
scheduleManager.updateStatusSchedule(sched, TriggerStatus.READY);\n
(\&User '\& + user.getUserId() + \& has active schedule \& + sched.getScheduleName());\n\n
ret.put(\&status\&, \&success\&);\n
ret.put(\&message\&, \&flow \& + sched.getFlowName() + \& active from Schedules.\&);\\n
private void ajaxDeActiveSched(HttpServletRequest req, Map&String, Object& ret, User user) throws ServletException {\n
int scheduleId = getIntParam(req, \&scheduleId\&);\n
sched = scheduleManager.getSchedule(scheduleId);\n
} catch (ScheduleManagerException e) {\n
throw new ServletException(e);\n
if (sched == null) {\n
ret.put(\&message\&, \&Schedule with ID \& + scheduleId + \& does not exist\&);\n
ret.put(\&status\&, \&error\&);\\n
Project project = projectManager.getProject(sched.getProjectId());\n\n
if (project == null) {\n
ret.put(\&message\&, \&Project \& + sched.getProjectId() + \& does not exist\&);\n
ret.put(\&status\&, \&error\&);\\n
if (!hasPermission(project, user, Type.SCHEDULE)) {\n
ret.put(\&status\&, \&error\&);\n
ret.put(\&message\&, \&Permission denied. Cannot remove schedule with id \& + scheduleId);\\n
scheduleManager.updateStatusSchedule(sched, TriggerStatus.PAUSED);\n
(\&User '\& + user.getUserId() + \& has active schedule \& + sched.getScheduleName());\n\n
ret.put(\&status\&, \&success\&);\n
ret.put(\&message\&, \&flow \& + sched.getFlowName() + \& deactive from Schedules.\&);\\n
}\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E以上就是修改Azkaban使其支持Cron表达式的整个过程,其实核心思想是怎样获取下一个执行时间点,代码核心是新增类 CronBasedScheduleLoader 实现 ScheduleLoader接口 和 新增CronExprChecker类,实现 ConditionChecker接口。\u003C\u002Fp\u003E&,&state&:&published&,&sourceUrl&:&&,&pageCommentsCount&:0,&canComment&:false,&snapshotUrl&:&&,&slug&:,&publishedTime&:&T15:19:18+08:00&,&url&:&\u002Fp\u002F&,&title&:&Azkaban二次开发-支持Cron表达式&,&summary&:&Azkaban原生的定时器只能支持从指定时间起,按时间步长周期性地调度任务。这种调度方式使用简单,也比较容易理解,但是我们有些任务调度时间是非周期性的,例如只在周六和周日的某个时间点执行,这样原生的定时器就不能支持。为此我们需要改造Azkaban的定时…&,&reviewingCommentsCount&:0,&meta&:{&previous&:null,&next&:null},&commentPermission&:&anyone&,&commentsCount&:6,&likesCount&:6}},&annotationDetail&:null,&commentsCount&:4,&likesCount&:27,&FULLINFO&:true}},&User&:{&zhanggj&:{&isFollowed&:false,&name&:&张高境&,&headline&:&&,&avatarUrl&:&https:\u002F\\u002Fda8e974dc_s.jpg&,&isFollowing&:false,&type&:&people&,&slug&:&zhanggj&,&bio&:&编程+分析&,&hash&:&cfd46e561eb9714cbb3bc&,&uid&:16,&isOrg&:false,&description&:&&,&badge&:{&identity&:null,&bestAnswerer&:null},&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhanggj&,&avatar&:{&id&:&da8e974dc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}},&Comment&:{},&favlists&:{}},&me&:{},&global&:{&experimentFeatures&:{&ge3&:&ge3_9&,&ge2&:&ge2_1&,&nwebStickySidebar&:&sticky&,&searchSectionStyle&:&loosen&,&androidPassThroughPush&:&all&,&newMore&:&new&,&nwebQAGrowth&:&experiment&,&showTipInLiveDetailsPage&:&true&,&nwebFeedAd&:&experiment&,&newSign&:&newVersion&,&liveReviewBuyBar&:&live_review_buy_bar_2&,&qawebRelatedReadingsContentControl&:&open&,&marketTabBanner&:&market_tab_banner_show&,&liveStore&:&ls_a2_b2_c1_f2&,&qawebThumbnailAbtest&:&new&,&nwebSearch&:&nweb_search_heifetz&,&searchHybridTabs&:&without-tabs&,&enableVoteDownReasonMenu&:&enable&,&showVideoUploadAttention&:&true&,&isOffice&:&false&,&enableTtsPlay&:&false&,&newQuestionDiversion&:&false&,&wechatShareModal&:&wechat_share_modal_show&,&newLiveFeedMediacard&:&old&,&hybridZhmoreVideo&:&no&,&recommendationAbtest&:&new&,&qrcodeLogin&:&qrcode&,&isShowUnicomFreeEntry&:&unicom_free_entry_off&,&newMobileColumnAppheader&:&new_header&,&questionRecommendReadingsAbtest&:&similar&,&androidDbCommentWithRepinRecord&:&open&,&androidDbRecommendAction&:&open&,&zcmLighting&:&zcm&,&androidDbFeedHashTagStyle&:&button&,&appStoreRateDialog&:&close&,&newAppViewRelatedAd&:&no&,&default&:&None&,&isNewNotiPanel&:&no&,&androidDbRepinSelection&:&open&,&nwebRelatedAdvert&:&default&,&qaStickySidebar&:&sticky_sidebar&,&androidProfilePanel&:&panel_b&,&nwebWriteAnswer&:&experiment&}},&columns&:{&next&:{},&dataeye&:{&following&:false,&canManage&:false,&href&:&\u002Fapi\u002Fcolumns\u002Fdataeye&,&name&:&DataEye数据中心&,&creator&:{&slug&:&zhanggj&},&url&:&\u002Fdataeye&,&slug&:&dataeye&,&avatar&:{&id&:&v2-ad&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&}}},&columnPosts&:{},&columnSettings&:{&colomnAuthor&:[],&uploadAvatarDetails&:&&,&contributeRequests&:[],&contributeRequestsTotalCount&:0,&inviteAuthor&:&&},&postComments&:{},&postReviewComments&:{&comments&:[],&newComments&:[],&hasMore&:true},&favlistsByUser&:{},&favlistRelations&:{},&promotions&:{},&switches&:{&couldSetPoster&:false},&draft&:{&titleImage&:&&,&titleImageSize&:{},&isTitleImageFullScreen&:false,&canTitleImageFullScreen&:false,&title&:&&,&titleImageUploading&:false,&error&:&&,&content&:&&,&draftLoading&:false,&globalLoading&:false,&pendingVideo&:{&resource&:null,&error&:null}},&drafts&:{&draftsList&:[],&next&:{}},&config&:{&userNotBindPhoneTipString&:{}},&recommendPosts&:{&articleRecommendations&:[],&columnRecommendations&:[]},&env&:{&edition&:{&baidu&:false,&yidianzixun&:false,&qqnews&:false},&isAppView&:false,&appViewConfig&:{&content_padding_top&:128,&content_padding_bottom&:56,&content_padding_left&:16,&content_padding_right&:16,&title_font_size&:22,&body_font_size&:16,&is_dark_theme&:false,&can_auto_load_image&:true,&app_info&:&OS=iOS&},&isApp&:false,&userAgent&:{&ua&:&Mozilla\u002F5.0 (compatible, MSIE 11, Windows NT 6.3; Trident\u002F7.0; rv:11.0) like Gecko&,&browser&:{&name&:&IE&,&version&:&11&,&major&:&11&},&engine&:{&version&:&7.0&,&name&:&Trident&},&os&:{&name&:&Windows&,&version&:&8.1&},&device&:{},&cpu&:{}}},&message&:{&newCount&:0},&pushNotification&:{&newCount&:0}}}

我要回帖

更多关于 阿里大数据平台架构 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信