taoCMS-基于php+sqlite最小巧的CMS http://www.taocms.org/ taoCMS是基于php+sqlite/mysql的国内最小(100Kb左右)的功能完善的CMS管理系统 2019-04-24 taoCMS-基于php+sqlite最小巧的CMS 1164 你见过哪些厉害的领导?

总结一下我遇到的几个好科长的共同点吧。

精通业务,公正公平,知人善任,敢于负责,集思广益,善于协调,关心下属。

精通业务:你所负责的科室的所有职责,你都熟悉,管辖范围内任何一个下属的任务,你都能予以正确指导,拿出思路,指出提高的方向,甚至,自己能临时给他当B角。领导,领导,你得领着干,身先士卒,不能光发号施令不亲自动手,得会指导,让大家按你的思路干。

知人善任:知道每个下属的长处和缺点,用人扬长避短。能干的,能者多劳,却不能让他太累,不能干的,教会他干,督促他干,寸有所长,让他在合适的位置发挥自己的优势,不能有的累死有的闲死。也不能干让驴耕田牛拉磨的事。

公正公平:遇到晋升、评优、外出培训等机会时,优先推荐工作努力表现优秀的同志,激励他干得更好。体制内,不好好干活的,虽然你不能辞退他,不犯错误不能给他降级,但也不能让他占到便宜,干得差反而拿得多。在职权范围内尽量奖勤罚懒。让实干者实惠。

敢于负责:下属的做法如果事先得到你的批准,那么他做事的后果,你要负责。干好了,要表扬下属,替下属争取荣誉,不要跟下属抢功劳,干不好,上级批评你们科室,你得替下属兜着,这样才让下属愿意跟你干。否则,有好处你先跑在前面抢,一出事就把别人推上去挡枪,那别人就寒心了。

集思广益:经常召开科室会议,在分配工作的同时,征求大家对科室下一步工作的好的建议,对好的建议要及时采纳,不恰当的,说明原因,但不要讽刺挖苦,不能打击别人提建议的积极性。

善于协调:协调科室内部人事关系,发生矛盾及早解决,和为贵,凝聚全部人员的力量。需要其它科室或业务单位配合的工作,你作为科长要出面进行协调,不能指望科员和别的科的科长协调,不要指望科员和业务单位的老总协调,不对等的话人家不会理你的茬。

关心下属:在干好工作的同时,关心下属的生活情况,通过科室聚会等机会,了解下属思想动态,如果下属有困难,在力所能及的情况下帮助解决。

]]>
taoCMS-基于php+sqlite最小巧的CMS 2019-04-02 02:04:11
1163 一位创业6年CEO的忠告:不要等公司倒闭,才思考这3个问题 创业6年,

我犯过的3个常识性错误


之所以说是“常识性错误”,是因为这些错误背后的道理看起来都太简单了。不过,故事都是真实的,犯过的错是血淋淋的。

 

1.不关注竞争对手

 

牛逼的公司都很喜欢这么说。亚马逊的创始人贝索斯很多场合都半开玩笑地说:“不要关注你的竞争对手,因为他们又不给你钱。”

 

微信的创始人张小龙,最近在点评“子弹短信”APP的时候也说:“看了一眼截图,还不值得我安装体验一下。我们将来会落后的原因可能是因为不了解用户,而不是因为我们不了解竞争对手。”

 

听起来都特别有道理,对不对?我曾经也是这么觉得的。因为我们公司做的游戏曾经也在中国的APP畅销榜第一待过一年。那个时候,我也从来不看竞争对手的游戏。


直到有一天,我下了一堆友商的产品体验了一下,才大吃一惊:原来友商的产品画面、玩法的进化程度,已经大大超过了我的想象。于是我才明白:

了解竞争对手,其实是非常好的了解用户的途径。而不关注竞争对手,其实是一种鸵鸟心态,把自己封闭起来,然后自我感觉良好。


用户喜欢什么、需要什么,他们不一定有机会用自己的嘴巴告诉你。但是,他们一定会用自己的钱和时间投票。如果某个竞品的市场表现好,一定说明了它在某些方面更符合用户的需要。

 

关注和了解竞争对手后,初级的方法是:照抄。而高级一点的方法是:洞察用户在使用产品背后的需求,找到更好的解决方案,融入到自己的产品里。

 

贝索斯没有告诉我们的是,其实他的公司有个“竞争情报组”(competitive intelligence)。


在美国职场人脉网站LinkedIn上面一搜,可以搜到亚马逊有很多这样的职位在招聘。而他们的主要工作,就是在其他电商网站上大量购买商品,评测他们的各种服务,然后汇报给贝索斯。

 

2.不想花大力气招聘关键人才

 

设想一下,公司要开展一项具有挑战性的全新业务,需要一个新的负责人。如果你是CEO,你会从已有的得力干将里提拔一个,还是从市场上招聘一个有类似经验的人?

 

过去几年,我大部分时候都选择了前者。为什么呢?因为这样做最轻松啊。


但最后的结果往往不尽人意。团队往往需要浪费很多时间,走很多弯路,才能最终走到正确的方向上。究其原因,对不熟悉的领域,我们常常低估了做成的难度,而又高估了学习的速度。

 

举例来说,同样是拍电影,文艺片和商业片,爱情片和动作片,动画片和真人片,需要的导演、团队都是完全不一样的。


如果我们忽视了其中的差异,非让拍爱情片的去拍动作片,最后拍出来的有可能是爱情动作片。

 

3.不相信管理

 

这点说起来特别可笑,但确实是真事。

 

我在之前的公众号中写过:

我曾经在腾讯工作了近4年,但混的特别差。没有带过任何人,没有任何管理经验。在我离职前一年的一次考评中,我甚至被打了“C”,几乎是劝退的意思。

 

我创业之初的几个重要伙伴,也都是来自腾讯。但是因为我在腾讯的资历比较浅,所以我找来的人,也都没什么管理经验。如果他们当时就知道我被打了C,估计都不会跟我一起创业。

 

但是好死不死,创业的第一个项目居然做成了。一堆没有任何管理经验的人,也能做成事,这让我更相信了一件事:管理不重要。


一个认为管理不重要的人,会把公司做成什么样子呢?答案就是一团糟。

 

1)我会对所有我看不爽的事情,甚至各种执行细节指手画脚,美其名曰“扁平化”管理。

 

公司人少的时候,问题还不严重。可公司上了几百人的时候,问题立刻出来了:因为我什么事情都可能管,所以很多负责人对业务缺少完整的决策权。没了权力,责任也模糊了。

 

更严重的是,时间久了,大家都不把事情当自己的事,只把事情当成是“老板的事情”。


现在,我对扁平化有了更深的理解:可以向所有人了解情况,但是只跟少数人讨论决策。

 

2)选择关键岗位负责人时,我不看重管理经验,只看重专业能力。

 

结果就是我选中的这个负责人,经常把自己累个半死,但是团队的整体产出完全不行。


带团队,真的是需要经验的。专业能力,和带团队能力,是两种关联性比较低的能力。前者是对事情的理解,而后者需要对人的理解,完全不是一回事。

 

3)我拒绝在公司搞绩效考评和职级评估。

 

前面说了,因为我自己就是绩效考评的受害者,所以我不想在自己的公司里搞这套。但是后来同事们不干了:他们需要来自公司的反馈,他们需要可预期、有节奏的成长反馈。


所以2017年,公司到了300人的时候,我才在同事们的压力下,把绩效考评补上。


终于有一天我明白了,如果我觉得自己的管理理念很先进、很时尚,那一定是错觉。那只是因为公司小而已。如果公司人数多了,就应该老老实实学习大公司的做法。


管理是一门很复杂的科学,没有足够经验时就想搞创新,太难了。

创业6年,

我犯过的几个高级错误

 

错误既然有低级,那就应该有高级。接下来就写写高级错误。

 

所谓高级错误,就是这些错误背后的道理并非显而易见。有些我今天认为错误的事情,还在被国内一些商学院被作为正面案例。

 

1.用KPI驱动业务

 

KPI(Key Performance Indicator),简单来说,就是把薪酬、奖金跟一些关键业务指标挂钩。关键指标可能是收入、利润、股价、活跃用户数、增长率等等。

 

这是一种相当流行的做法。我在腾讯上班的前同事经常发一张很搞笑的表情图,图上是马化腾瞪着眼睛看着你,下面写着一行字:“KPI完成了吗?”

 

用KPI来驱动业务会带来什么问题呢?可能带来2个问题。

 

1)短视

 

2016年,我非常希望公司的海外业务能快速增长。有一次,我把产品和市场团队的负责人叫到一起开会,讨论怎样才能在一个季度里做到收入增长30%。团队表示非常困难。

 

也许是那天我情绪上来了,也许是受到了那段时间流行的“狼性文化”的影响,我要求团队必须达成目标。并且,为了增强团队的动力,我承诺了一笔数额不菲的奖金。

 

结果你猜怎么样?团队果然达成了30%的增长目标。但同时,也带来了另外一个后果:产品数据在接下来的几个月里显著下滑。

 

等我仔细回顾时,才发现为了达成目标、获得奖金,团队对产品做了非常短视的改动:把一些商品做了大幅的打折,并且把一些过去非常稀缺、从不售卖的商品,以很低的价格卖出去了。


于是我才明白:制定短期目标,并且让目标跟奖金强挂钩,就是在逼团队变得短视。

 

一个季度太短,那一年够长吗?有时候也不够。有些投资人会要求被投公司对赌利润,这也会让公司变得短视。

 

亚马逊和Google在近两年的公开文件中显示,他们都不再把高管的薪酬跟业绩指标挂钩。这两个公司都是“长期主义”的坚定拥护者。


但是苹果的CEO库克的薪酬,却与股价高度挂钩。如果乔布斯还在,相信应该不会是这样的。

 

2)动作变形

如果医院有一个很强的KPI是降低死亡率,会导致什么结果?会导致医院拒绝接受真正有生命危险的病人。显然,这与医院救死扶伤的初衷相违背。

 

大部分理发店会给理发师提供办卡收入的提成。这样导致的结果就是,理发师一定会一边剪头发,一边喋喋不休地劝你办卡。

 

我国很多的法院,以“调解率”作为法官的重要考核指标。法官的基本职责,从公正审判,变成了调解矛盾,类似居委会大妈的角色。


所以,即使是看起来很好的初衷,在KPI的强指引下,也会导致动作变形。

 

综上所述,KPI是一无是处吗?也不是。如果要完成的目标非常清晰,且完全知道该怎么做的情况下,是可以用KPI的。


我有个在招商银行工作的朋友,KPI有20多个,甚至还有“级差地租系数”这样非人类能理解的指标。如果KPI能定成这样,也许是有效的。

 

2.以差异化、创新为目标

 

2014年~2016年间,我在公司成立了一个名为“孵化中心”的部门,专门做各种新项目的预研工作。这些新项目,都有一个明确的立项标准:一定要创新,一定要差异化,否则不做。

 

我为什么会把创新看得这么重呢?一方面,我把过去的成功归因到创新上。另一方面,我也在中欧商学院听到了一种非常吸引人的理论:与其更好,不如不同。

 

把创新看得重,以创新为目标,对吗?错了,且这是一个新手非常容易犯的错。


做公司,本质就是要做出符合他人需要的产品和服务。他人就是一切。而“创新”,是一个从自己的主观视角出发的描述。他人需要的,其实不是创新。他人需要的,就是“更好”。

 

我去现场看过几次锤子手机的发布会。每次看完,我都会为罗永浩捏一把汗。因为锤子手机在“创新”上投入的实在太多,而在“更好”上投入的却又太少。

 

作为一个每天被使用六七个小时的随身设备,用户需要的不是“无限屏”,“TNT大屏操作系统”这样不太实用的创新。用户需要的,就是更好的屏幕、更高清的摄像头,更流畅的系统。

 

创新并不代表更好。现有的产品之所以流行,说明本身就不是很差。一个创新的,但不比现有产品更好的东西,其实是非常糟糕的。这也是为什么,我们公司“孵化中心”曾经做出来的产品,虽然是创新的,但大部分都非常失败。

 

为什么说这是一个新手容易犯的错呢?因为新手很容易以自我为中心。或者说,大部分正常人都是以自我为中心。

 

“我创新,所以我牛逼。你们不喜欢,只是因为你们品味太差。” 这是每一个创新者的内心独白。

 

翻看我年初写的公众号,现在有些已经看不下去了:因为确实有些文章写的太自我、太矫情了,完全没考虑读者的接受度。站在用户视角来思考,需要经过长期的训练。甚至同样的人,换一个领域,这种训练都还要再来一遍。


那么“差异化”这个词对不对呢?只有一种差异化是对的:用户定位的差异化。

比如别人的手机是卖给年轻人的,我的手机是专门卖给老年人的,所以把字体设计得特别大,这是对的。


或者我的手机是专门卖给非洲人的,针对黑人做了面部识别和美颜,这也是对的。


除此之外,所有刻意地追求差异化都是错的。

 

与其差异化,不如更好。这是一个非常痛的领悟。

创业6年,

关于人的领悟

 

1.CEO最常犯的错误,就是高估自己

 

为什么CEO会常常高估自己呢?有两个原因:

 

1)身边的真正的批评声音少

 

人都喜欢表扬,不喜欢批评,这是本性。而且,我们大部分时候根本分不清:当别人在说“yes”的时候,到底是思考后的认同,还只是在迎合、拍马屁。

 

如果不是特别注意,时间一久,CEO身边就会很容易聚集一堆拍马屁的人。如果一个人发现自己说什么都对,那很快就会飘起来,开始高估自己。

 

2) CEO的正确判断力常常是通过信息优势获得的,而大部分人没有意识到这一点。

 

前几天在湖畔大学听阿里的一个高管分享。他说阿里巴巴之所以能很快速成长,其中一个很重要的原因是:马云很早就不再骑马打仗,而是在全球范围内进行高段位的交流。

 

可以想象,如果每天跟你聊天的都是各国元首,一流经济学家,全球最成功公司的CEO,那你一定会变得很厉害。

 

当然,大部分人做不到马云那样。但是即便如此,CEO可获得信息的来源质量也是公司里最高的。所以,当CEO做出高质量决策的时候,很容易产生自己比其他人聪明的幻觉。


我是怎么意识到自己有这个幻觉的呢?是通过打游戏认识到的。

 

炉石传说、守望先锋、吃鸡,都是公平竞技的游戏。这些游戏一出,我也跟着同事们一起玩。我本来觉得自己很聪明,一定能玩得比别人好。

 

但我很快发现:其实我只是中等水平而已。在信息完全公平的情况下,我根本做不到比别人好。而且很多同事能够做出来的复杂操作,我根本做不出来。

 

认识到自己并不是最牛逼、最聪明的,是CEO开始关注他人、授权他人的第一步。

 

2.开展新业务,应该优先找人,而不是优先想解决方案

 

这里的“找人”并不是找一般的专业人员,而是要找真正有全局视角的领导者。


开展新业务的时候,我们最常犯的错误,就是以为自己很懂,以为新业务看起来没什么难的,然后找来一些工程师,或者找来一些二三流业务负责人就开始指挥。

 

之所以会犯这种错误,归根结底还是因为觉得自己比别人聪明,对自己不熟悉的行业缺少敬畏心,觉得自己想到了别人没想到的破局点。

 

前两天我看到美团开始也做游戏了。招聘网站上放出了一些“游戏策划”,“游戏开发工程师”的职位,但是没有看到“游戏制作人”或者“游戏业务负责人”这样的高级职位。面对媒体的好奇,美团的王慧文回应说:“我就试试,别多想。”

 

当然我相信,以王兴、王慧文的厉害和成熟程度,是绝对不可能犯这种“以为自己比别人聪明”的错的。

 

3.不应该过分依赖人的学习能力

 

有一次,我跟一个知名创业公司的CEO聊天。他说了一句非常震惊我,且绝对不会在公开场合说的话:“我们公司在创立之初就定下一条规则,就是不培养人。”

 

后来我才理解了他的话。不培养人,其实就是倒逼自己,找到与业务最匹配的人。这个做法对员工来说未必好,但对公司来说却是短期内性价比最高的方案。

 

这个CEO的做法有些极端,与我曾经的做法刚好相反。我曾经以为,人可以在很短时间内学会自己不熟悉的领域。所以我投入很大精力在培训上,而对招聘的投入明显不足。

 

这两种做法,哪种更好?短期来看,显然是招聘到对的人成本更低。因为培养一个人,存在巨大的不确定性,且有着最贵的成本:时间。

 

但从长期来看,员工的能力发展对公司的成长也至关重要。因为市场、竞争都是动态变化的。今天有效的打法,过三个月也许就没用了。一个没有学习能力的团队会很快被淘汰。


现在的我同样重视培训,重视学习。但是我也深刻地意识到:学习能力,是一种锦上添花。业务的展开,不能依赖人的学习能力。

 

4.人不需要是全面、完美的

 

最懂业务、懂技术的人,常常不懂得怎么带好团队。逻辑思考能力很强的人,对他人的感知力常常很差。一个人的优点和缺点常常是一体的,就好像是硬币的正反面。

 

但成为一个好的业务负责人,常常既需要对业务深刻的理解,又需要强大的领导力。既需要丝丝入扣的逻辑思考,也需要无微不至的用户感知。这样的人有吗?有,但太少了。


这个时候,就需要身边有其他的人来帮他补足。比如,业务能力很强的负责人,常常需要搭配一个管理、规划能力很强的副手。

 

当然,如果有些短板能自己补上,那就更好。但这种改变,往往需要更多的耐心和时间。

我有个朋友,曾经在工作沟通中很不注意他人的感受,导致很难跟他人展开配合。但是她后来成了人妻,又生了小孩,渐渐变得温柔多了。


最近我和几个好朋友,也是其他公司的CEO,进行了年底相互批评的活动。我的朋友犀利地指出了我的两个缺点:爱装逼,以及容易满足。


有朋友能说真话批评,是一件非常幸运的事。因为缺点只有被指出来,才有被改正的机会。

 

借此机会,写在这里,希望大家新的一年多多监督。

作者:王信文,莉莉丝游戏CEO。公众号:王信文(ID:kenny_ideas)每周四凌晨更新,用简单的语言表达深刻思考,关注商业、技术、人类未来。


]]>
taoCMS-基于php+sqlite最小巧的CMS 2019-02-11 21:02:49
1162 分布式任务调度平台XXL-JOB 一、简介

1.1 概述

XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

1.2 特性

  • 1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
  • 2、动态:支持动态修改任务状态、启动/停止任务,以及终止运行中任务,即时生效;
  • 3、调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现并支持集群部署,可保证调度中心HA;
  • 4、执行器HA(分布式):任务分布式执行,任务"执行器"支持集群部署,可保证任务执行HA;
  • 5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
  • 6、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
  • 7、路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
  • 8、故障转移:任务路由策略选择"故障转移"情况下,如果执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求。
  • 9、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
  • 10、任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务;
  • 11、任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试;
  • 12、任务失败告警;默认提供邮件方式失败告警,同时预留扩展接口,可方面的扩展短信、钉钉等告警方式;
  • 13、分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
  • 14、动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
  • 15、事件触发:除了"Cron方式"和"任务依赖方式"触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
  • 16、任务进度监控:支持实时监控任务进度;
  • 17、Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
  • 18、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
  • 19、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本;
  • 20、命令行任务:原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;
  • 21、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
  • 22、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
  • 23、自定义任务参数:支持在线配置调度任务入参,即时生效;
  • 24、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
  • 25、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
  • 26、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
  • 27、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
  • 28、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
  • 29、全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;
  • 30、跨平台:原生提供通用HTTP任务Handler(Bean任务,"HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;
  • 31、国际化:调度中心支持国际化设置,提供中文、英文两种可选语言,默认为中文;
  • 32、容器化:提供官方docker镜像,并实时更新推送dockerhub,进一步实现产品开箱即用;

1.3 发展

于2015年中,我在github上创建XXL-JOB项目仓库并提交第一个commit,随之进行系统结构设计,UI选型,交互设计……

于2015-11月,XXL-JOB终于RELEASE了第一个大版本V1.0, 随后我将之发布到OSCHINA,XXL-JOB在OSCHINA上获得了@红薯的热门推荐,同期分别达到了OSCHINA的“热门动弹”排行第一和git.oschina的开源软件月热度排行第一,在此特别感谢红薯,感谢大家的关注和支持。

于2015-12月,我将XXL-JOB发表到我司内部知识库,并且得到内部同事认可。

于2016-01月,我司展开XXL-JOB的内部接入和定制工作,在此感谢袁某和尹某两位同事的贡献,同时也感谢内部其他给与关注与支持的同事。

于2017-05-13,在上海举办的 "第62期开源中国源创会" 的 "放码过来" 环节,我登台对XXL-JOB做了演讲,台下五百位在场观众反响热烈(图文回顾 )。

于2017-10-22,又拍云 Open Talk 联合 Spring Cloud 中国社区举办的 "进击的微服务实战派上海站",我登台对XXL-JOB做了演讲,现场观众反响热烈并在会后与XXL-JOB用户热烈讨论交流。

于2017-12-11,XXL-JOB有幸参会《InfoQ ArchSummit全球架构师峰会》,并被拍拍贷架构总监"杨波老师"在专题 "微服务原理、基础架构和开源实践" 中现场介绍。

于2017-12-18,XXL-JOB参与"2017年度最受欢迎中国开源软件"评比,在当时已录入的约九千个国产开源项目中角逐,最终进入了前30强。

于2018-01-15,XXL-JOB参与"2017码云最火开源项目"评比,在当时已录入的约六千五百个码云项目中角逐,最终进去了前20强。

于2018-04-14,iTechPlus在上海举办的 "2018互联网开发者大会",我登台对XXL-JOB做了演讲,现场观众反响热烈并在会后与XXL-JOB用户热烈讨论交流。

于2018-05-27,在上海举办的 "第75期开源中国源创会" 的 "架构" 主题专场,我登台进行“基础架构与中间件图谱”主题演讲,台下上千位在场观众反响热烈(图文回顾 )。

我司大众点评目前已接入XXL-JOB,内部别名《Ferrari》(Ferrari基于XXL-JOB的V1.1版本定制而成,新接入应用推荐升级最新版本)。 据最新统计, 自2016-01-21接入至2017-12-01期间,该系统已调度约100万次,表现优异。新接入应用推荐使用最新版本,因为经过数十个版本的更新,系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升,核心功能更加稳定高效。

至今,XXL-JOB已接入多家公司的线上产品线,接入场景如电商业务,O2O业务和大数据作业等,截止最新统计时间为止,XXL-JOB已接入的公司包括不限于:

- 1、大众点评;
- 2、山东学而网络科技有限公司;
- 3、安徽慧通互联科技有限公司;
- 4、人人聚财金服;
- 5、上海棠棣信息科技股份有限公司
- 6、运满满
- 7、米其林 (中国区)
- 8、妈妈联盟
- 9、九樱天下(北京)信息技术有限公司
- 10、万普拉斯科技有限公司(一加手机)
- 11、上海亿保健康管理有限公司
- 12、海尔馨厨 (海尔)
- 13、河南大红包电子商务有限公司
- 14、成都顺点科技有限公司
- 15、深圳市怡亚通
- 16、深圳麦亚信科技股份有限公司
- 17、上海博莹科技信息技术有限公司
- 18、中国平安科技有限公司
- 19、杭州知时信息科技有限公司
- 20、博莹科技(上海)有限公司
- 21、成都依能股份有限责任公司
- 22、湖南高阳通联信息技术有限公司
- 23、深圳市邦德文化发展有限公司
- 24、福建阿思可网络教育有限公司
- 25、优信二手车
- 26、上海悠游堂投资发展股份有限公司
- 27、北京粉笔蓝天科技有限公司
- 28、中秀科技(无锡)有限公司
- 29、武汉空心科技有限公司
- 30、北京蚂蚁风暴科技有限公司
- 31、四川互宜达科技有限公司
- 32、钱包行云(北京)科技有限公司
- 33、重庆欣才集团
- 34、咪咕互动娱乐有限公司(中国移动)
- 35、北京诺亦腾科技有限公司
- 36、增长引擎(北京)信息技术有限公司
- 37、北京英贝思科技有限公司
- 38、刚泰集团
- 39、深圳泰久信息系统股份有限公司
- 40、随行付支付有限公司
- 41、广州瀚农网络科技有限公司
- 42、享点科技有限公司
- 43、杭州比智科技有限公司
- 44、圳临界线网络科技有限公司
- 45、广州知识圈网络科技有限公司
- 46、国誉商业上海有限公司
- 47、海尔消费金融有限公司,嗨付、够花 (海尔)
- 48、广州巴图鲁信息科技有限公司
- 49、深圳市鹏海运电子数据交换有限公司
- 50、深圳市亚飞电子商务有限公司
- 51、上海趣医网络有限公司
- 52、聚金资本
- 53、北京父母邦网络科技有限公司
- 54、中山元赫软件科技有限公司
- 55、中商惠民(北京)电子商务有限公司
- 56、凯京集团
- 57、华夏票联(北京)科技有限公司
- 58、拍拍贷
- 59、北京尚德机构在线教育有限公司
- 60、任子行股份有限公司
- 61、北京时态电子商务有限公司
- 62、深圳卷皮网络科技有限公司
- 63、北京安博通科技股份有限公司
- 64、未来无线网
- 65、厦门瓷禧网络有限公司
- 66、北京递蓝科软件股份有限公司
- 67、郑州创海软件科技公司
- 68、北京国槐信息科技有限公司
- 69、浪潮软件集团
- 70、多立恒(北京)信息技术有限公司
- 71、广州极迅客信息科技有限公司
- 72、赫基(中国)集团股份有限公司
- 73、海投汇
- 74、上海润益创业孵化器管理股份有限公司
- 75、汉纳森(厦门)数据股份有限公司
- 76、安信信托
- 77、岚儒财富
- 78、捷道软件
- 79、湖北享七网络科技有限公司
- 80、湖南创发科技责任有限公司
- 81、深圳小安时代互联网金融服务有限公司
- 82、湖北享七网络科技有限公司
- 83、钱包行云(北京)科技有限公司
- 84、360金融 (360)
- 85、易企秀
- 86、摩贝(上海)生物科技有限公司
- 87、广东芯智慧科技有限公司
- 88、联想集团 (联想)
- 89、怪兽充电
- 90、行圆汽车
- 91、深圳店店通科技邮箱公司
- 92、京东 (京东)
- 93、米庄理财
- 94、咖啡易融
- 95、梧桐诚选
- 96、恒大地产 (恒大)
- 97、昆明龙慧
- 98、上海涩瑶软件
- 99、易信 (网易)
- 100、铜板街
- 101、杭州云若网络科技有限公司
- 102、特百惠(中国)有限公司
- 103、常山众卡运力供应链管理有限公司
- 104、深圳立创电子商务有限公司
- 105、杭州智诺科技股份有限公司
- 106、北京云漾信息科技有限公司
- 107、深圳市多银科技有限公司
- 108、亲宝宝
- 109、上海博卡软件科技有限公司
- 110、智慧树在线教育平台
- 111、米族金融
- 112、北京辰森世纪
- 113、云南滇医通
- 114、广州市分领网络科技有限责任公司
- 115、浙江微能科技有限公司
- 116、上海馨飞电子商务有限公司
- 117、上海宝尊电子商务有限公司
- 118、直客通科技技术有限公司
- 119、科度科技有限公司
- 120、上海数慧系统技术有限公司
- 121、我的医药网
- 122、多粉平台
- 123、铁甲二手机
- 124、上海海新得数据技术有限公司
- 125、深圳市珍爱网信息技术有限公司 (珍爱网)
- 126、小蜜蜂
- 127、吉荣数科技
- 128、上海恺域信息科技有限公司
- 129、广州荔支网络有限公司(荔枝FM)
- 130、杭州闪宝科技有限公司
- 131、北京互联新网科技发展有限公司
- 132、誉道科技
- 133、山西兆盛房地产开发有限公司
- ……

更多接入的公司,欢迎在 登记地址 登记,登记仅仅为了产品推广。

欢迎大家的关注和使用,XXL-JOB也将拥抱变化,持续发展。

1.4 下载

文档地址

源码仓库地址

源码仓库地址Release Download
https://github.com/xuxueli/xxl-jobDownload
http://gitee.com/xuxueli0323/xxl-jobDownload

中央仓库地址

<!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${最新稳定版本}</version>
</dependency>

技术交流

1.5 环境

  • JDK:1.7+
  • Servlet/JSP Spec:3.1/2.3
  • Tomcat:8.5.x/Jetty9.2.x
  • Spring-boot:1.5.x/Spring4.x
  • Mysql:5.6+
  • Maven:3+

二、快速入门

2.1 初始化“调度数据库”

请下载项目源码并解压,获取 "调度数据库初始化SQL脚本" 并执行即可,正常情况下应该生成16张表。

"调度数据库初始化SQL脚本" 位置为:

/xxl-job/doc/db/tables_xxl_job.sql

调度中心支持集群部署,集群情况下各节点务必连接同一个mysql实例;

如果mysql做主从,调度中心集群节点务必强制走主库;

2.2 编译源码

解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可,源码结构如下:

xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
    :xxl-job-executor-sample-spring:Spring版本,通过Spring容器管理执行器,比较通用,推荐这种方式;
    :xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器;
    :xxl-job-executor-sample-jfinal:JFinal版本,通过JFinal管理执行器;
    :xxl-job-executor-sample-nutz:Nutz版本,通过Nutz管理执行器;

2.3 配置部署“调度中心”

调度中心项目:xxl-job-admin
作用:统一管理任务调度平台上调度任务,负责触发调度执行,并且提供任务管理平台。

步骤一:调度中心配置:

调度中心配置文件地址:

/xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties

调度中心配置内容说明:

### 调度中心JDBC链接:链接地址请保持和 2.1章节 所创建的调度数据库的地址一致
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl-job?Unicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root_pwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

### 报警邮箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

### 登录账号
xxl.job.login.username=admin
xxl.job.login.password=123456

### 调度中心通讯TOKEN,非空时启用
xxl.job.accessToken=

### 调度中心国际化设置,默认为中文版本,值设置为“en”时切换为英文版本
xxl.job.i18n=

步骤二:部署项目:

如果已经正确进行上述配置,可将项目编译打包部署。 调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址),登录后运行界面如下图所示

输入图片说明

至此“调度中心”项目已经部署成功。

步骤三:调度中心集群(可选):

调度中心支持集群部署,提升调度系统容灾和可用性。

调度中心集群部署时,几点要求和建议:

  • DB配置保持一致;
  • 登陆账号配置保持一致;
  • 集群机器时钟保持一致(单机集群忽视);
  • 建议:推荐通过nginx为调度中心集群做负载均衡,分配域名。调度中心访问、执行器回调配置、调用API服务等操作均通过该域名进行。

其他:Docker 镜像方式搭建调度中心:

  • 下载镜像
// Docker地址:https://hub.docker.com/r/xuxueli/xxl-job-admin/
docker pull xuxueli/xxl-job-admin
  • 创建容器并运行
docker run -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin  -d xuxueli/xxl-job-admin

/**
* 如需自定义 mysql 等配置,可通过 "PARAMS" 指定;
* 配置项参考文件:/xxl-job/xxl-job-admin/src/main/resources/application.properties
*/
docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl-job?Unicode=true&characterEncoding=UTF-8" -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin  -d xuxueli/xxl-job-admin

2.4 配置部署“执行器项目”

“执行器”项目:xxl-job-executor-sample-spring (提供多种版本执行器供选择,现以Spring版本为例,可直接使用,也可以参考其并将现有项目改造成执行器)
作用:负责接收“调度中心”的调度并执行;可直接部署执行器,也可以将执行器集成到现有业务项目中。

步骤一:maven依赖

确认pom文件中引入了 "xxl-job-core" 的maven依赖;

步骤二:执行器配置

执行器配置,配置文件地址:

/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties

执行器配置,配置内容说明:

### xxl-job admin address list:调度中心部署跟地址:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调"。
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin

### xxl-job executor address:执行器"AppName"和地址信息配置:AppName执行器心跳注册分组依据;地址信息用于"调度中心请求并触发任务"和"执行器注册"。执行器默认端口为9999,执行器IP默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用。单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip=
xxl.job.executor.port=9999

### xxl-job, access token:执行器通讯TOKEN,非空时启用
xxl.job.accessToken=
    
### xxl-job log path:执行器运行日志文件存储的磁盘位置,需要对该路径拥有读写权限
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/

### xxl-job log retention days:执行器Log文件定期清理功能,指定日志保存天数,日志文件过期自动删除。限制至少保持3天,否则功能不生效;
xxl.job.executor.logretentiondays=-1

步骤三:执行器组件配置

执行器组件,配置文件地址:

/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml

执行器组件,配置内容说明:

<!-- 配置01、JobHandler 扫描路径:自动扫描容器中JobHandler -->
<context:component-scan base-package="com.xxl.job.executor.service.jobhandler" />

<!-- 配置02、执行器 -->
<bean id="xxlJobExecutor" class="com.xxl.job.core.executor.XxlJobExecutor" init-method="start" destroy-method="destroy" >
    <!-- 执行器注册中心地址[选填],为空则关闭自动注册 -->
    <property name="adminAddresses" value="${xxl.job.admin.addresses}" />
    <!-- 执行器AppName[选填],为空则关闭自动注册 -->
    <property name="appName" value="${xxl.job.executor.appname}" />
    <!-- 执行器IP[选填],为空则自动获取 -->
    <property name="ip" value="${xxl.job.executor.ip}" />
    <!-- 执行器端口号[选填],小于等于0则自动获取 -->
    <property name="port" value="${xxl.job.executor.port}" />
    <!-- 访问令牌[选填],非空则进行匹配校验 -->
    <property name="accessToken" value="${xxl.job.accessToken}" />
    <!-- 执行器日志路径[选填],为空则使用默认路径 -->
    <property name="logPath" value="${xxl.job.executor.logpath}" />
    <!-- 日志保存天数[选填],值大于3时生效 -->
    <property name="logRetentionDays" value="${xxl.job.executor.logretentiondays}" />
</bean>

步骤四:部署执行器项目:

如果已经正确进行上述配置,可将执行器项目编译打部署,系统提供多种执行器Sample示例项目,选择其中一个即可,各自的部署方式如下。

xxl-job-executor-sample-springboot:项目编译打包成springboot类型的可执行JAR包,命令启动即可;
xxl-job-executor-sample-spring:项目编译打包成WAR包,并部署到tomcat中。
xxl-job-executor-sample-jfinal:同上
xxl-job-executor-sample-nutz:同上

至此“执行器”项目已经部署结束。

步骤五:执行器集群(可选):

执行器支持集群部署,提升调度系统可用性,同时提升任务处理能力。

执行器集群部署时,几点要求和建议:

  • 执行器回调地址(xxl.job.admin.addresses)需要保持一致;执行器根据该配置进行执行器自动注册等操作。
  • 同一个执行器集群内AppName(xxl.job.executor.appname)需要保持一致;调度中心根据该配置动态发现不同集群的在线执行器列表。

2.5 开发第一个任务“Hello World”

本示例以新建一个 “GLUE模式(Java)” 运行模式的任务为例。更多有关任务的详细配置,请查看“章节三:任务详解”。 ( “GLUE模式(Java)”的执行代码托管到调度中心在线维护,相比“Bean模式任务”需要在执行器项目开发部署上线,更加简便轻量)

前提:请确认“调度中心”和“执行器”项目已经成功部署并启动;

步骤一:新建任务:

登录调度中心,点击下图所示“新建任务”按钮,新建示例任务。然后,参考下面截图中任务的参数配置,点击保存。

输入图片说明

输入图片说明

步骤二:“GLUE模式(Java)” 任务开发:

请点击任务右侧 “GLUE” 按钮,进入 “GLUE编辑器开发界面” ,见下图。“GLUE模式(Java)” 运行模式的任务默认已经初始化了示例任务代码,即打印Hello World。 ( “GLUE模式(Java)” 运行模式的任务实际上是一段继承自IJobHandler的Java类代码,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务,详细介绍请查看第三章节)

输入图片说明

输入图片说明

步骤三:触发执行:

请点击任务右侧 “执行” 按钮,可手动触发一次任务执行(通常情况下,通过配置Cron表达式进行任务调度出发)。

步骤四:查看日志:

请点击任务右侧 “日志” 按钮,可前往任务日志界面查看任务日志。 在任务日志界面中,可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮,可进入日志控制台查看实时执行日志。

输入图片说明

在日志控制台,可以Rolling方式实时查看任务在执行器一侧运行输出的日志信息,实时监控任务进度;

输入图片说明

三、任务详解

配置属性详细说明:

- 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;
- 任务描述:任务的描述信息,便于任务管理;
- 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;
    FIRST(第一个):固定选择第一个机器;
    LAST(最后一个):固定选择最后一个机器;
    ROUND(轮询):;
    RANDOM(随机):随机选择在线的机器;
    CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
    LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;
    LEAST_RECENTLY_USED(最近最久未使用):最久为使用的机器优先被选举;
    FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
    BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
    SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
    
- Cron:触发任务执行的Cron表达式;
- 运行模式:
    BEAN模式:任务以JobHandler方式维护在执行器端;需要结合 "JobHandler" 属性匹配执行器中任务;
    GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务;
    GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "shell" 脚本;
    GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "python" 脚本;
    GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "php" 脚本;
    GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "nodejs" 脚本;
    GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "PowerShell" 脚本;
- JobHandler:运行模式为 "BEAN模式" 时生效,对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值;
- 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;
    单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
    丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
    覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
- 子任务:每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
- 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;
- 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;
- 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;
- 负责人:任务的负责人;
- 执行参数:任务执行所需的参数,多个参数时用逗号分隔,任务执行时将会把多个参数转换成数组传入;

3.1 BEAN模式

任务逻辑以JobHandler的形式存在于“执行器”所在项目中,开发流程如下:

步骤一:执行器项目中,开发JobHandler:

 - 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”;
 - 2、注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例;
 - 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。
 - 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
(可参考Sample示例执行器中的DemoJobHandler,见下图)

输入图片说明

步骤二:调度中心,新建调度任务

参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "BEAN模式",JobHandler属性填写任务注解“@JobHandler”中定义的值;

输入图片说明

原生内置Bean模式任务

为方便用户参考与快速实用,示例执行器内原生提供多个Bean模式任务Handler,可以直接配置实用,如下:

  • demoJobHandler:简单示例任务,任务内部模拟耗时任务逻辑,用户可在线体验Rolling Log等功能;
  • shardingJobHandler:分片示例任务,任务内部模拟处理分片参数,可参考熟悉分片任务;
  • httpJobHandler:通用HTTP任务Handler;业务方只需要提供HTTP链接即可,不限制语言、平台;
  • commandJobHandler:通用命令行任务Handler;业务方只需要提供命令行即可;如 “pwd”命令;

3.2 GLUE模式(Java)

任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler。开发流程如下:

步骤一:调度中心,新建调度任务:

参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(Java)";

输入图片说明

步骤二:开发任务代码:

选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。

版本回溯功能(支持30个版本的版本回溯):在GLUE任务的Web IDE界面,选择右上角下拉框“版本回溯”,会列出该GLUE的更新历史,选择相应版本即可显示该版本代码,保存后GLUE代码即回退到对应的历史版本;

输入图片说明

3.3 GLUE模式(Shell)

步骤一:调度中心,新建调度任务

参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(Shell)";

步骤二:开发任务代码:

选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。

该模式的任务实际上是一段 "shell" 脚本;

输入图片说明

3.4 GLUE模式(Python)

步骤一:调度中心,新建调度任务

参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(Python)";

步骤二:开发任务代码:

选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。

该模式的任务实际上是一段 "python" 脚本;

输入图片说明

3.5 GLUE模式(NodeJS)

步骤一:调度中心,新建调度任务

参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(NodeJS)";

步骤二:开发任务代码:

选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。

该模式的任务实际上是一段 "nodejS" 脚本;

3.6 GLUE模式(PHP)

同上

3.7 GLUE模式(PowerShell)

同上

四、任务管理

4.0 配置执行器

点击进入"执行器管理"界面, 如下图: 输入图片说明

1、"调度中心OnLine:"右侧显示在线的"调度中心"列表, 任务执行结束后, 将会以failover的模式进行回调调度中心通知执行结果, 避免回调的单点风险;
2、"执行器列表" 中显示在线的执行器列表, 可通过"OnLine 机器"查看对应执行器的集群机器。

点击按钮 "+新增执行器" 弹框如下图, 可新增执行器配置:

输入图片说明

执行器属性说明

AppName: 是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;
排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
注册方式:调度中心获取执行器地址的方式;
    自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
    手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
机器地址:"注册方式"为"手动录入"时有效,支持人工维护执行器的地址信息;

4.1 新建任务

进入任务管理界面,点击“新增任务”按钮,在弹出的“新增任务”界面配置任务属性后保存即可。详情页参考章节 "三、任务详解"。

4.2 编辑任务

进入任务管理界面,选中指定任务。点击该任务右侧“编辑”按钮,在弹出的“编辑任务”界面更新任务属性后保存即可,可以修改设置的任务属性信息:

4.3 编辑GLUE代码

该操作仅针对GLUE任务。

选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发。可参考章节 "3.2 GLUE模式(Java)"。

4.4 启动/停止任务

可对任务进行“启动”和“停止”操作。 需要注意的是,此处的启动/停止仅针对任务的后续调度触发行为,不会影响到已经触发的调度任务,如需终止已经触发的调度任务,可查看“4.8 终止运行中的任务”

输入图片说明

4.5 手动触发一次调度

点击“执行”按钮,可手动触发一次任务调度,不影响原有调度规则。

输入图片说明

4.6 查看调度日志

点击“日志”按钮,可以查看任务历史调度日志。在历史调入日志界面可查看每次任务调度的调度结果、执行结果等,点击“执行日志”按钮可查看执行器完整日志。

输入图片说明

输入图片说明

调度时间:"调度中心"触发本次调度并向"执行器"发送任务执行信号的时间;
调度结果:"调度中心"触发本次调度的结果,200表示成功,500或其他表示失败;
调度备注:"调度中心"触发本次调度的日志信息;
执行器地址:本次任务执行的机器地址
运行模式:触发调度时任务的运行模式,运行模式可参考章节 "三、任务详解";
任务参数:本地任务执行的入参
执行时间:"执行器"中本次任务执行结束后回调的时间;
执行结果:"执行器"中本次任务执行的结果,200表示成功,500或其他表示失败;
执行备注:"执行器"中本次任务执行的日志信息;
操作:
    "执行日志"按钮:点击可查看本地任务执行的详细日志信息;详见“4.7 查看执行日志”;
    "终止任务"按钮:点击可终止本地调度对应执行器上本任务的执行线程,包括未执行的阻塞任务一并被终止;

4.7 查看执行日志

点击执行日志右侧的 “执行日志” 按钮,可跳转至执行日志界面,可以查看业务代码中打印的完整日志,如下图;

输入图片说明

4.8 终止运行中的任务

仅针对执行中的任务。 在任务日志界面,点击右侧的“终止任务”按钮,将会向本次任务对应的执行器发送任务终止请求,将会终止掉本次任务,同时会清空掉整个任务执行队列。

输入图片说明

任务终止时通过 "interrupt" 执行线程的方式实现, 将会触发 "InterruptedException" 异常。因此如果JobHandler内部catch到了该异常并消化掉的话, 任务终止功能将不可用。

因此, 如果遇到上述任务终止不可用的情况, 需要在JobHandler中应该针对 "InterruptedException" 异常进行特殊处理 (向上抛出) , 正确逻辑如下:

try{
    // TODO
} catch (Exception e) {
    if (e instanceof InterruptedException) {
        throw e;
    }
    logger.warn("{}", e);
}

而且,在JobHandler中开启子线程时,子线程也不可catch处理"InterruptedException",应该主动向上抛出。

4.9 删除执行日志

在任务日志界面,选中执行器和任务之后,点击右侧的"删除"按钮将会出现"日志清理"弹框,弹框中支持选择不同类型的日志清理策略,选中后点击"确定"按钮即可进行日志清理操作; 输入图片说明

输入图片说明

4.10 删除任务

点击删除按钮,可以删除对应任务。

输入图片说明

五、总体设计

5.1 源码目录介绍

- /doc :文档资料
- /db :“调度数据库”建表脚本
- /xxl-job-admin :调度中心,项目源码
- /xxl-job-core :公共Jar依赖
- /xxl-job-executor-samples :执行器,Sample示例项目(大家可以在该项目上进行开发,也可以将现有项目改造生成执行器项目)

5.2 “调度数据库”配置

XXL-JOB调度模块基于Quartz集群实现,其“调度数据库”是在Quartz的11张集群mysql表基础上扩展而成。

XXL-JOB首先定制了Quartz原生表结构前缀(XXL_JOB_QRTZ_)。

然后,在此基础上新增了几张张扩展表,如下: - XXL_JOB_QRTZ_TRIGGER_GROUP:执行器信息表,维护任务执行器信息; - XXL_JOB_QRTZ_TRIGGER_REGISTRY:执行器注册表,维护在线的执行器和调度中心机器地址信息; - XXL_JOB_QRTZ_TRIGGER_INFO:调度扩展信息表: 用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等; - XXL_JOB_QRTZ_TRIGGER_LOG:调度日志表: 用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等; - XXL_JOB_QRTZ_TRIGGER_LOGGLUE:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;

因此,XXL-JOB调度数据库共计用于16张数据库表。

5.3 架构设计

5.3.1 设计思想

将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求。

将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。

因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;

5.3.2 系统组成

  • 调度模块(调度中心): 负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块; 支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。
  • 执行模块(执行器): 负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效; 接收“调度中心”的执行请求、终止请求和日志请求等。

5.3.3 架构图

输入图片说明

5.4 调度模块剖析

5.4.1 quartz的不足

Quartz作为开源作业调度中的佼佼者,是作业调度的首选。但是集群环境中Quartz采用API的方式对任务进行管理,从而可以避免上述问题,但是同样存在以下问题:

  • 问题一:调用API的的方式操作任务,不人性化;
  • 问题二:需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
  • 问题三:调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况加,此时调度系统的性能将大大受限于业务;
  • 问题四:quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。

XXL-JOB弥补了quartz的上述不足之处。

5.4.2 RemoteHttpJobBean

常规Quartz的开发,任务逻辑一般维护在QuartzJobBean中,耦合很严重。XXL-JOB中“调度模块”和“任务模块”完全解耦,调度模块中的所有调度任务使用同一个QuartzJobBean,即RemoteHttpJobBean。不同的调度任务将各自参数维护在各自扩展表数据中,当触发RemoteHttpJobBean执行时,将会解析不同的任务参数发起远程调用,调用各自的远程执行器服务。

这种调用模型类似RPC调用,RemoteHttpJobBean提供调用代理的功能,而执行器提供远程服务的功能。

5.4.3 调度中心HA(集群)

基于Quartz的集群方案,数据库选用Mysql;集群分布式并发环境中使用QUARTZ定时任务调度,会在各个节点会上报任务,存到数据库中,执行时会从数据库中取出触发器来执行,如果触发器的名称和执行时间相同,则只有一个节点去执行此任务。

# for cluster
org.quartz.jobStore.tablePrefix = XXL_JOB_QRTZ_
org.quartz.scheduler.instanceId: AUTO
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 1000

5.4.4 调度线程池

调度采用线程池方式实现,避免单线程因阻塞而引起任务调度延迟。

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 50
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

5.4.5 @DisallowConcurrentExecution

XXL-JOB调度模块的“调度中心”默认不使用该注解,即默认开启并行机制,因为RemoteHttpJobBean为公共QuartzJobBean,这样在多线程调度的情况下,调度模块被阻塞的几率很低,大大提高了调度系统的承载量。

XXL-JOB的每个调度任务虽然在调度模块是并行调度执行的,但是任务调度传递到任务模块的“执行器”确实串行执行的,同时支持任务终止。

5.4.6 misfire

错过了触发时间,处理规则。 可能原因:服务重启;调度线程被QuartzJobBean阻塞,线程被耗尽;某个任务启用了@DisallowConcurrentExecution,上次调度持续阻塞,下次调度被错过;

quartz.properties中关于misfire的阀值配置如下,单位毫秒:

org.quartz.jobStore.misfireThreshold: 60000

Misfire规则: withMisfireHandlingInstructionDoNothing:不触发立即执行,等待下次调度; withMisfireHandlingInstructionIgnoreMisfires:以错过的第一个频率时间立刻开始执行; withMisfireHandlingInstructionFireAndProceed:以当前时间为触发频率立刻触发一次执行;

XXL-JOB默认misfire规则为:withMisfireHandlingInstructionDoNothing

CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();

5.4.7 日志回调服务

调度模块的“调度中心”作为Web服务部署时,一方面承担调度中心功能,另一方面也为执行器提供API服务。

调度中心提供的"日志回调服务API服务"代码位置如下:

xxl-job-admin#com.xxl.job.admin.controller.JobApiController.callback

“执行器”在接收到任务执行请求后,执行任务,在执行结束之后会将执行结果回调通知“调度中心”:

5.4.8 任务HA(Failover)

执行器如若集群部署,调度中心将会感知到在线的所有执行器,如“127.0.0.1:9997, 127.0.0.1:9998, 127.0.0.1:9999”。

当任务"路由策略"选择"故障转移(FAILOVER)"时,当调度中心每次发起调度请求时,会按照顺序对执行器发出心跳检测请求,第一个检测为存活状态的执行器将会被选定并发送调度请求。

调度成功后,可在日志监控界面查看“调度备注”,如下; 输入图片说明

“调度备注”可以看出本地调度运行轨迹,执行器的"注册方式"、"地址列表"和任务的"路由策略"。"故障转移(FAILOVER)"路由策略下,调度中心首先对第一个地址进行心跳检测,心跳失败因此自动跳过,第二个依然心跳检测失败…… 直至心跳检测第三个地址“127.0.0.1:9999”成功,选定为“目标执行器”;然后对“目标执行器”发送调度请求,调度流程结束,等待执行器回调执行结果。

5.4.9 调度日志

调度中心每次进行任务调度,都会记录一条任务日志,任务日志主要包括以下三部分内容:

  • 任务信息:包括“执行器地址”、“JobHandler”和“执行参数”等属性,点击任务ID按钮可查看,根据这些参数,可以精确的定位任务执行的具体机器和任务代码;
  • 调度信息:包括“调度时间”、“调度结果”和“调度日志”等,根据这些参数,可以了解“调度中心”发起调度请求时具体情况。
  • 执行信息:包括“执行时间”、“执行结果”和“执行日志”等,根据这些参数,可以了解在“执行器”端任务执行的具体情况;

调度日志,针对单次调度,属性说明如下:

  • 执行器地址:任务执行的机器地址;
  • JobHandler:Bean模式表示任务执行的JobHandler名称;
  • 任务参数:任务执行的入参;
  • 调度时间:调度中心,发起调度的时间;
  • 调度结果:调度中心,发起调度的结果,SUCCESS或FAIL;
  • 调度备注:调度中心,发起调度的备注信息,如地址心跳检测日志等;
  • 执行时间:执行器,任务执行结束后回调的时间;
  • 执行结果:执行器,任务执行的结果,SUCCESS或FAIL;
  • 执行备注:执行器,任务执行的备注信息,如异常日志等;
  • 执行日志:任务执行过程中,业务代码中打印的完整执行日志,见“4.7 查看执行日志”;

5.4.10 任务依赖

原理:XXL-JOB中每个任务都对应有一个任务ID,同时,每个任务支持设置属性“子任务ID”,因此,通过“任务ID”可以匹配任务依赖关系。

当父任务执行结束并且执行成功时,将会根据“子任务ID”匹配子任务依赖,如果匹配到子任务,将会主动触发一次子任务的执行。

在任务日志界面,点击任务的“执行备注”的“查看”按钮,可以看到匹配子任务以及触发子任务执行的日志信息,如无信息则表示未触发子任务执行,可参考下图。

输入图片说明

输入图片说明

5.4.11 全异步化 & 轻量级

  • 全异步化设计:XXL-JOB系统中业务逻辑在远程执行器执行,触发流程全异步化设计。相比直接在quartz的QuartzJobBean中执行业务逻辑,极大的降低了调度线程占用时间;
    • 异步调度:调度中心每次任务触发时仅发送一次调度请求,该调度请求首先推送“异步调度队列”,然后异步推送给远程执行器
    • 异步执行:执行器会将请求存入“异步执行队列”并且立即响应调度中心,异步运行。
  • 轻量级设计:XXL-JOB调度中心中每个JOB逻辑非常 “轻”,在全异步化的基础上,单个JOB一次运行平均耗时基本在 "10ms" 之内(基本为一次请求的网络开销);因此,可以保证使用有限的线程支撑大量的JOB并发运行;

得益于上述两点优化,理论上默认配置下的调度中心,单机能够支撑 5000 任务并发运行稳定运行;

实际场景中,由于调度中心与执行器网络ping延迟不同、DB读写耗时不同、任务调度密集程度不同,会导致任务量上限会上下波动。

如若需要支撑更多的任务量,可以通过 "调大调度线程数" 、"降低调度中心与执行器ping延迟" 和 "提升机器配置" 几种方式优化。

5.5 任务 "运行模式" 剖析

5.5.1 "Bean模式" 任务

开发步骤:可参考 "章节三" ; 原理:每个Bean模式任务都是一个Spring的Bean类实例,它被维护在“执行器”项目的Spring容器中。任务类需要加“@JobHandler(value="名称")”注解,因为“执行器”会根据该注解识别Spring容器中的任务。任务类需要继承统一接口“IJobHandler”,任务逻辑在execute方法中开发,因为“执行器”在接收到调度中心的调度请求时,将会调用“IJobHandler”的execute方法,执行任务逻辑。

5.5.2 "GLUE模式(Java)" 任务

开发步骤:可参考 "章节三" ; 原理:每个 "GLUE模式(Java)" 任务的代码,实际上是“一个继承自“IJobHandler”的实现类的类代码”,“执行器”接收到“调度中心”的调度请求时,会通过Groovy类加载器加载此代码,实例化成Java对象,同时注入此代码中声明的Spring服务(请确保Glue代码中的服务和类引用在“执行器”项目中存在),然后调用该对象的execute方法,执行任务逻辑。

5.5.3 GLUE模式(Shell) + GLUE模式(Python) + GLUE模式(NodeJS)

开发步骤:可参考 "章节三" ; 原理:脚本任务的源码托管在调度中心,脚本逻辑在执行器运行。当触发脚本任务时,执行器会加载脚本源码在执行器机器上生成一份脚本文件,然后通过Java代码调用该脚本;并且实时将脚本输出日志写到任务日志文件中,从而在调度中心可以实时监控脚本运行情况;

目前支持的脚本类型如下:

- shell脚本:任务运行模式选择为 "GLUE模式(Shell)"时支持 "shell" 脚本任务;
- python脚本:任务运行模式选择为 "GLUE模式(Python)"时支持 "python" 脚本任务;
- nodejs脚本:务运行模式选择为 "GLUE模式(NodeJS)"时支持 "nodejs" 脚本任务;

脚本任务通过 Exit Code 判断任务执行结果,状态码可参考章节 "5.15 任务执行结果说明";

5.5.4 执行器

执行器实际上是一个内嵌的Jetty服务器,默认端口9999(配置项:xxl.job.executor.port)。

在项目启动时,执行器会通过“@JobHandler”识别Spring容器中“Bean模式任务”,以注解的value属性为key管理起来。

“执行器”接收到“调度中心”的调度请求时,如果任务类型为“Bean模式”,将会匹配Spring容器中的“Bean模式任务”,然后调用其execute方法,执行任务逻辑。如果任务类型为“GLUE模式”,将会加载GLue代码,实例化Java对象,注入依赖的Spring服务(注意:Glue代码中注入的Spring服务,必须存在与该“执行器”项目的Spring容器中),然后调用execute方法,执行任务逻辑。

5.5.5 任务日志

XXL-JOB会为每次调度请求生成一个单独的日志文件,需要通过 "XxlJobLogger.log" 打印执行日志,“调度中心”查看执行日志时将会加载对应的日志文件。

(历史版本通过重写LOG4J的Appender实现,存在依赖限制,该方式在新版本已经被抛弃)

日志文件存放的位置可在“执行器”配置文件进行自定义,默认目录格式为:/data/applogs/xxl-job/jobhandler/“格式化日期”/“数据库调度日志记录的主键ID.log”。

在JobHandler中开启子线程时,子线程将会将会把日志打印在父线程即JobHandler的执行日志中,方便日志追踪。

5.6 通讯模块剖析

5.6.1 一次完整的任务调度通讯流程

- 1、“调度中心”向“执行器”发送http调度请求: “执行器”中接收请求的服务,实际上是一台内嵌jetty服务器,默认端口9999;
- 2、“执行器”执行任务逻辑;
- 3、“执行器”http回调“调度中心”调度结果: “调度中心”中接收回调的服务,是针对执行器开放一套API服务;

5.6.2 通讯数据加密

调度中心向执行器发送的调度请求时使用RequestModel和ResponseModel两个对象封装调度请求参数和响应数据, 在进行通讯之前底层会将上述两个对象对象序列化,并进行数据协议以及时间戳检验,从而达到数据加密的功能;

5.7 任务注册, 任务自动发现

自v1.5版本之后, 任务取消了"任务执行机器"属性, 改为通过任务注册和自动发现的方式, 动态获取远程执行器地址并执行。

AppName: 每个执行器机器集群的唯一标示, 任务注册以 "执行器" 为最小粒度进行注册; 每个任务通过其绑定的执行器可感知对应的执行器机器列表;
注册表: 见"XXL_JOB_QRTZ_TRIGGER_REGISTRY"表, "执行器" 在进行任务注册时将会周期性维护一条注册记录,即机器地址和AppName的绑定关系; "调度中心" 从而可以动态感知每个AppName在线的机器列表;
执行器注册: 任务注册Beat周期默认30s; 执行器以一倍Beat进行执行器注册, 调度中心以一倍Beat进行动态任务发现; 注册信息的失效时间被三倍Beat; 
执行器注册摘除:执行器销毁时,将会主动上报调度中心并摘除对应的执行器机器信息,提高心跳注册的实时性;

为保证系统"轻量级"并且降低学习部署成本,没有采用Zookeeper作为注册中心,采用DB方式进行任务注册发现;

5.8 任务执行结果

自v1.6.2之后,任务执行结果通过 "IJobHandler" 的返回值 "ReturnT" 进行判断; 当返回值符合 "ReturnT.code == ReturnT.SUCCESS_CODE" 时表示任务执行成功,否则表示任务执行失败,而且可以通过 "ReturnT.msg" 回调错误信息给调度中心; 从而,在任务逻辑中可以方便的控制任务执行结果;

5.9 分片广播 & 动态分片

执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发对应集群中所有执行器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;

"分片广播" 以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。

"分片广播" 和普通任务开发流程一致,不同之处在于可以可以获取分片参数,获取分片参数进行分片业务处理。

  • Java语言任务获取分片参数方式:BEAN、GLUE模式(Java)
// 可参考Sample示例执行器中的示例任务"ShardingJobHandler"了解试用 
ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
  • 脚本语言任务获取分片参数方式:GLUE模式(Shell)、GLUE模式(Python)、GLUE模式(Nodejs)
// 脚本任务入参固定为三个,依次为:任务传参、分片序号、分片总数。以Shell模式任务为例,获取分片参数代码如下
echo "分片序号 index = $2"
echo "分片总数 total = $3"

分片参数属性说明:

index:当前分片序号(从0开始),执行器集群列表中当前执行器的序号;
total:总分片数,执行器集群的总机器数量;

该特性适用场景如:

  • 1、分片任务场景:10个执行器的集群来处理10w条数据,每台机器只需要处理1w条数据,耗时降低10倍;
  • 2、广播任务场景:广播执行器机器运行shell脚本、广播集群节点进行缓存更新等

5.10 访问令牌(AccessToken)

为提升系统安全性,调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯;

调度中心和执行器,可通过配置项 "xxl.job.accessToken" 进行AccessToken的设置。

调度中心和执行器,如果需要正常通讯,只有两种设置;

  • 设置一:调度中心和执行器,均不设置AccessToken;关闭安全性校验;
  • 设置二:调度中心和执行器,设置了相同的AccessToken;

5.11 调度中心API服务

调度中心提供了API服务,主要分为两种类型:

5.11.1 提供给执行器的API服务:

1、任务结果回调服务;
2、执行器注册服务;
3、执行器注册摘除服务;
4、触发任务单次执行服务,支持任务根据业务事件触发;

API服务位置:com.xxl.job.core.biz.AdminBiz.java
API服务请求参考代码:com.xxl.job.adminbiz.AdminBizTest.java

5.11.2 提供给业务的API服务:

1、任务列表查询;
2、任务新增;
3、任务更新;
4、任务删除;
5、任务启动;
6、任务停止;
7、任务触发;

API服务位置:com.xxl.job.admin.controller.JobInfoController.java
API服务请求参考代码:可参考任务界面操作的ajax请求。任何ajax接口均可配置成为API服务,只需在待启用的API服务上添加 “@PermessionLimit(limit = false)” 注解取消登陆态拦截即可;

5.12 执行器API服务

执行器提供了API服务,供调度中心选择使用,目前提供的API服务有:

1、心跳检测:调度中心使用
2、忙碌检测:调度中心使用
3、触发任务执行:调度中心使用;本地进行任务开发时,可使用该API服务模拟触发任务;
4、获取Rolling Log:调度中心使用
5、终止任务:调度中心使用

API服务位置:com.xxl.job.core.biz.ExecutorBiz
API服务请求参考代码:com.xxl.job.executor.ExecutorBizTest

5.13 故障转移 & 失败重试

一次完整任务流程包括"调度(调度中心) + 执行(执行器)"两个阶段。

  • "故障转移"发生在调度阶段,在执行器集群部署时,如果某一台执行器发生故障,该策略支持自动进行Failover切换到一台正常的执行器机器并且完成调度请求流程。
  • "失败重试"发生在"调度 + 执行"两个阶段,支持通过自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;

5.14 执行器灰度上线

调度中心与业务解耦,只需部署一次后常年不需要维护。但是,执行器中托管运行着业务作业,作业上线和变更需要重启执行器,尤其是Bean模式任务。 执行器重启可能会中断运行中的任务。但是,XXL-JOB得益于自建执行器与自建注册中心,可以通过灰度上线的方式,避免因重启导致的任务中断的问题。

步骤如下:

  • 1、执行器改为手动注册,下线一半机器列表(A组),线上运行另一半机器列表(B组);
  • 2、等待A组机器任务运行结束并编译上线;执行器注册地址替换为A组;
  • 3、等待B组机器任务运行结束并编译上线;执行器注册地址替换为A组+B组; 操作结束;

5.15 任务执行结果说明

系统根据以下标准判断任务执行结果,可参考之。

--Bean/Glue(Java)Glue(Shell) 等脚本任务
成功IJobHandler.SUCCESS0
失败IJobHandler.FAIL-1(非0状态码)

5.16 任务超时控制

支持设置任务超时时间,任务运行超时的情况下,将会主动中断任务;

需要注意的是,任务超时中断时与任务终止机制(可查看“4.8 终止运行中的任务”)类似,也是通过 "interrupt" 中断任务,因此业务代码需要将 "InterruptedException" 外抛,否则功能不可用。

5.17 跨平台 & 跨语言

跨平台、跨语言主要体现在以下两个方面:

  • 1、提供Java、Python、PHP……等十来种任务模式,可参考章节 “5.5 任务 "运行模式" ”;理论上可扩展任意语言任务模式;
  • 2、提供基于HTTP的任务Handler(Bean任务,JobHandler="HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;

5.18 任务失败告警

默认提供邮件失败告警,可扩展短信、钉钉等方式,扩展代码位置为 "JobFailMonitorHelper.failAlarm";

5.19 调度中心Docker镜像构建

可以通过以下命令快速构建调度中心,并启动运行;

mvn clean package
docker build -t xuxueli/xxl-job-admin ./xxl-job-admin
docker run --name xxl-job-admin -p 8080:8080 -d xuxueli/xxl-job-admin

5.20 避免任务重复执行

调度密集或者耗时任务可能会导致任务阻塞,集群情况下调度组件小概率情况下会重复触发; 针对上述情况,可以通过结合 "单机路由策略(如:第一台、一致性哈希)" + "阻塞策略(如:单机串行、丢弃后续调度)" 来规避,最终避免任务重复执行。

5.21 命令行任务

原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可; 如任务参数 "pwd" 将会执行命令并输出数据;

六、版本更新日志

6.1 版本 V1.1.x,新特性[2015-12-05]

【于V1.1.x版本,XXL-JOB正式应用于我司,内部定制别名为 “Ferrari”,新接入应用推荐使用最新版本】

  • 1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
  • 2、动态:支持动态修改任务状态,动态暂停/恢复任务,即时生效;
  • 3、服务HA:任务信息持久化到mysql中,Job服务天然支持集群,保证服务HA;
  • 4、任务HA:某台Job服务挂掉,任务会平滑分配给其他的某一台存活服务,即使所有服务挂掉,重启时或补偿执行丢失任务;
  • 5、一个任务只会在其中一台服务器上执行;
  • 6、任务串行执行;
  • 7、支持自定义参数;
  • 8、支持远程任务执行终止;

6.2 版本 V1.2.x,新特性[2016-01-17]

  • 1、支持任务分组;

  • 2、支持“本地任务”、“远程任务”;

  • 3、底层通讯支持两种方式,Servlet方式 + JETTY方式;

  • 4、支持“任务日志”;

  • 5、支持“串行执行”,并行执行;

    说明:V1.2版本将系统架构按功能拆分为:

      - 调度模块(调度中心):负责管理调度信息,按照调度配置发出调度请求;
      - 执行模块(执行器):负责接收调度请求并执行任务逻辑;
      - 通讯模块:负责调度模块和任务模块之间的信息通讯;
    

    优点:

      - 解耦:任务模块提供任务接口,调度模块维护调度信息,业务相互独立;
      - 高扩展性;
      - 稳定性;
    

6.3 版本 V1.3.0,新特性[2016-05-19]

  • 1、遗弃“本地任务”模式,推荐使用“远程任务”,易于系统解耦,任务对应的JobHandler统称为“执行器”;

  • 2、遗弃“servlet”方式底层系统通讯,推荐使用JETTY方式,调度+回调双向通讯,重构通讯逻辑;

  • 3、UI交互优化:左侧菜单展开状态优化,菜单项选中状态优化,任务列表打开表格有压缩优化;

  • 4、【重要】“执行器”细分为:BEAN、GLUE两种开发模式,简介见下文:

    “执行器” 模式简介: - BEAN模式执行器:每个执行器都是Spring的一个Bean实例,XXL-JOB通过注解@JobHandler识别和调度执行器; -GLUE模式执行器:每个执行器对应一段代码,在线Web编辑和维护,动态编译生效,执行器负责加载GLUE代码和执行;

6.4 版本 V1.3.1,新特性[2016-05-23]

  • 1、更新项目目录结构:
    • /xxl-job-admin -------------------- 【调度中心】:负责管理调度信息,按照调度配置发出调度请求;
    • /xxl-job-core ----------------------- 公共依赖
    • /xxl-job-executor-example ------ 【执行器】:负责接收调度请求并执行任务逻辑;
    • /db ---------------------------------- 建表脚本
    • /doc --------------------------------- 用户手册
  • 2、在新的目录结构上,升级了用户手册;
  • 3、优化了一些交互和UI;

6.5 版本 V1.3.2,新特性[2016-05-28]

  • 1、调度逻辑进行事务包裹;
  • 2、执行器异步回调执行日志;
  • 3、【重要】在 “调度中心” 支持HA的基础上,扩展执行器的Failover支持,支持配置多执行期地址;

6.6 版本 V1.4.0 新特性[2016-07-24]

  • 1、任务依赖: 通过事件触发方式实现, 任务执行成功并回调时会主动触发一次子任务的调度, 多个子任务用逗号分隔;
  • 2、执行器底层实现代码进行重度重构, 优化底层建表脚本;
  • 3、执行器中任务线程分组逻辑优化: 之前根据执行器JobHandler进行线程分组,当多个任务复用Jobhanlder会导致相互阻塞。现改为根据调度中心任务进行任务线程分组,任务与任务执行相互隔离;
  • 4、执行器调度通讯方案优化, 通过Hex + HC实现建议RPC通讯协议, 优化了通讯参数的维护和解析流程;
  • 5、调度中心, 新建/编辑任务, 界面属性调整:
    • 5.1、任务新增/编辑界面中去除 "任务名JobName"属性 ,该属性改为系统自动生成: 该字段之前主要用于在 "调度中心" 唯一标示一个任务, 现实意义不大, 因此计划淡化掉该字段,改为系统生成UUID,从而简化任务新建的操作;
    • 5.2、任务新增/编辑界面中去除 "GLUE模式" 复选框位置调整, 改为贴近"JobHandler"输入框右侧;
    • 5.3、任务新增/编辑界面中去除 "报警阈值" 属性;
    • 5.4、任务新增/编辑界面中去除 "子任务Key" 属性, 每个任务全局任务Key可以从任务列表获取, 当本任务执行结束且成功后, 将会根据子任务Key匹配子任务并主动触发一次子任务执行;
  • 6、问题修复:
    • 6.1、执行器jetty关闭优化,解决一处可能导致jetty无法关闭的问题;
    • 6.2、执行器任务终止时,执行队列回调优化,解决一处导致任务无法回调的问题;
    • 6.3、调度中心中列表分页参数优化,解决一处因服务器限制post长度而引起的问题;
    • 6.4、执行器Jobhandler注解优化,解决一处因事务代理导致的容器无法加载JobHandler的问题;
    • 6.5、远程调度优化,禁用retry策略,解决一处可能导致重复调用的问题;

Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段, 地址见分支 V1.3 。新特性将会在master分支持续更新。

6.7 版本 V1.4.1 新特性[2016-09-06]

  • 1、项目成功推送maven中央仓库, 中央仓库地址以及依赖如下:
    <!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ -->
    <dependency>
        <groupId>com.xuxueli</groupId>
        <artifactId>xxl-job-core</artifactId>
        <version>${最新稳定版}</version>
    </dependency>
    
  • 2、为适配中央仓库规则, 项目groupId从com.xxl改为com.xuxueli。
  • 3、系统版本不在维护在项目跟pom中,各个子模块单独配置版本配置,解决子模块无法单独编译的问题;
  • 4、底层RPC通讯,传输数据的字节长度统计规则优化,可节省50%数据传输量;
  • 5、IJobHandler取消任务返回值,原通过返回值判断执行状态,逻辑改为:默认任务执行成功,仅在捕获异常时认定任务执行失败。
  • 6、系统公共弹框功能,插件化;
  • 7、底层表结构,表明统一大写;
  • 8、调度中心,异常处理器JSON响应的ContentType修改,修复浏览器不识别的问题;

6.8 版本 V1.4.2 新特性[2016-09-29]

  • 1、推送新版本 V1.4.2 至中央仓库, 大版本 V1.4 进入维护阶段;
  • 2、任务新增时,任务列表偏移问题修复;
  • 3、修复一处因bootstrap不支持模态框重叠而导致的样式错乱的问题, 在任务编辑时会出现该问题;
  • 4、调度超时和Handler匹配不到时,调度状态优化;
  • 5、因catch异常,导致任务不可终止的问题,给出解决方案, 见文档;

6.9 版本 V1.5.0 特性[2016-11-13]

  • 1、任务注册: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。
  • 2、"执行器" 新增参数 "AppName" : 是每个执行器集群的唯一标示AppName, 并周期性以AppName为对象进行自动注册。
  • 3、调度中心新增栏目 "执行器管理" : 管理在线的执行器, 通过属性AppName自动发现注册的执行器。只有被管理的执行器才允许被使用;
  • 4、"任务组"属性改为"执行器": 每个任务需要绑定指定的执行器, 调度地址通过绑定的执行器获取;
  • 5、抛弃"任务机器"属性: 通过任务绑定的执行器, 自动发现注册的远程执行器地址并触发调度请求。
  • 6、"公共依赖"中新增DBGlueLoader,基于原生jdbc实现GLUE源码的加载器,减少第三方依赖(mybatis,spring-orm等);精简和优化执行器测配置(针对GLUE任务),降低上手难度;
  • 7、表结构调整,底层重构优化;
  • 8、"调度中心"自动注册和发现,failover: 调度中心周期性自动注册, 任务回调时可以感知在线的所有调度中心地址, 通过failover的方式进行任务回调,避免回调单点风险。

6.10 版本 V1.5.1 特性[2016-11-13]

  • 1、底层代码重构和逻辑优化,POM清理以及CleanCode;
  • 2、Servlet/JSP Spec设定为3.0/2.2
  • 3、Spring升级至3.2.17.RELEASE版本;
  • 4、Jetty升级版本至8.2.0.v20160908;
  • 5、已推送V1.5.0和V1.5.1至Maven中央仓库;

6.10 版本 V1.5.2 特性[2017-02-28]

  • 1、IP工具类获取IP逻辑优化,IP静态缓存;
  • 2、执行器、调度中心,均支持自定义注册IP地址;解决机器多网卡时错误网卡注册的情况;
  • 3、任务跨天执行时生成多份日志文件的问题修复;
  • 4、底层日志底层日志调整,非敏感日志level调整为debug;
  • 5、升级数据库连接池c3p0版本;
  • 6、执行器log4j配置优化,去除无效属性;
  • 7、底层代码重构和逻辑优化以及CleanCode;
  • 8、GLUE依赖注入逻辑优化,支持别名注入;

6.11 版本 V1.6.0 特性[2017-03-13]

  • 1、通讯方案升级,原基于HEX的通讯模型调整为基于HTTP的B-RPC的通讯模型;
  • 2、执行器支持手动设置执行地址列表,提供开关切换使用注册地址还是手动设置的地址;
  • 3、执行器路由规则:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移;
  • 4、规范线程模型统一,统一线程销毁方案(通过listener或stop方法,容器销毁时销毁线程;Daemon方式有时不太理想);
  • 5、规范系统配置数据,通过配置文件统一管理;
  • 6、CleanCode,清理无效的历史参数;
  • 7、底层扩展数据结构以及相关表结构调整;
  • 8、新建任务默认为非运行状态;
  • 9、GLUE模式任务实例更新逻辑优化,原根据超时时间更新改为根据版本号更新,源码变动版本号加一;

6.12 版本 V1.6.1 特性[2017-03-25]

  • 1、Rolling日志;
  • 2、WebIDE交互重构;
  • 3、通讯增强校验,有效过滤非正常请求;
  • 4、权限增强校验,采用动态登录TOKEN(推荐接入内部SSO);
  • 5、数据库配置优化,解决乱码问题;

6.13 版本 V1.6.2 特性[2017-04-25]

  • 1、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
  • 2、JobHandler支持设置任务返回值,在任务逻辑中可以方便的控制任务执行结果;
  • 3、资源路径包含空格或中文时资源文件无法加载时,无法准确查看异常信息的问题处理。
  • 4、路由策越优化:循环和LFU路由策略计数器自增无上限问题和首次路由压力集中在首台机器的问题修复;

6.14 版本 V1.7.0 特性[2017-05-02]

  • 1、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python和Groovy等类型脚本;
  • 2、新增spring-boot类型执行器example项目;
  • 3、升级jetty版本至9.2;
  • 4、任务运行日志移除log4j组件依赖,改为底层自主实现,从而取消了对日志组件的依赖限制;
  • 5、执行器移除GlueLoader依赖,改为推送方式实现,从而GLUE源码加载不再依赖JDBC;
  • 6、登录拦截Redirect时获取项目名,解决非根据目录发布时跳转404问题;

6.15 版本 V1.7.1 特性[2017-05-08]

  • 1、运行日志读写编码统一为UTF-8,解决windows环境下日志乱码问题;
  • 2、通讯超时时间限定为10s,避免异常情况下调度线程占用;
  • 3、执行器,server启动、销毁和注册逻辑调整;
  • 4、JettyServer关闭逻辑优化,修复执行器无法正常关闭导致端口占用和频繁打印c3p0日志的问题;
  • 5、JobHandler中开启子线程时,支持子线程输出执行日志并通过Rolling查看。
  • 6、任务日志清理功能;
  • 7、弹框组件统一替换为layer;
  • 8、升级quartz版本至2.3.0;

6.16 版本 V1.7.2 特性[2017-05-17]

  • 1、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
  • 2、失败处理策略;调度失败时的处理策略,策略包括:失败告警(默认)、失败重试;
  • 3、通讯时间戳超时时间调整为180s;
  • 4、执行器与数据库彻底解耦,但是执行器需要配置调度中心集群地址。调度中心提供API供执行器回调和心跳注册服务,取消调度中心内部jetty,心跳周期调整为30s,心跳失效为三倍心跳;
  • 5、执行参数编辑时丢失问题修复;
  • 6、新增任务测试Demo,方便在开发时进行任务逻辑测试;

6.17 版本 V1.8.0 特性[2017-07-17]

  • 1、任务Cron更新逻辑优化,改为rescheduleJob,同时防止cron重复设置;
  • 2、API回调服务失败状态码优化,方便问题排查;
  • 3、XxlJobLogger的日志多参数支持;
  • 4、路由策略新增 "忙碌转移" 模式:按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
  • 5、路由策略代码重构;
  • 6、执行器重复注册问题修复;
  • 7、任务线程轮空30次后自动销毁,降低低频任务的无效线程消耗。
  • 8、执行器任务执行结果批量回调,降低回调频率提升执行器性能;
  • 9、springboot版本执行器,取消XML配置,改为类配置方式;
  • 10、执行日志,支持根据运行 "状态" 筛选日志;
  • 11、调度中心任务注册检测逻辑优化;

6.18 版本 V1.8.1 特性[2017-07-30]

  • 1、分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数处理分片任务;
  • 2、动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
  • 3、执行器JobHandler禁止命名冲突;
  • 4、执行器集群地址列表进行自然排序;
  • 5、调度中心,DAO层代码精简优化并且新增测试用例覆盖;
  • 6、调度中心API服务改为自研RPC形式,统一底层通讯模型;
  • 7、新增调度中心API服务测试Demo,方便在调度中心API扩展和测试;
  • 8、任务列表页交互优化,更换执行器分组时自动刷新任务列表,新建任务时默认定位在当前执行器位置;
  • 9、访问令牌(accessToken):为提升系统安全性,调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯;
  • 10、springboot版本执行器,升级至1.5.6.RELEASE版本;
  • 11、统一maven依赖版本管理;

6.19 版本 V1.8.2 特性[2017-09-04]

  • 1、项目主页搭建:提供中英文文档:http://www.xuxueli.com/xxl-job
  • 2、JFinal执行器Sample示例项目;
  • 3、事件触发:除了"Cron方式"和"任务依赖方式"触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
  • 4、执行器摘除:执行器销毁时,主动通知调度中心并摘除对应执行器节点,提高执行器状态感知的时效性。
  • 5、执行器手动设置IP时将会绑定Host;
  • 6、规范项目目录,方便扩展多执行器;
  • 7、解决执行器回调URL不支持配置HTTPS时问题;
  • 8、执行器回调线程销毁前, 批量回调队列中数据,防止任务结果丢失;
  • 9、调度中心任务监控线程销毁时,批量对失败任务告警,防止告警信息丢失;
  • 10、任务日志文件路径时间戳格式化时SimpleDateFormat并发问题解决;

6.20 版本 V1.9.0 特性[2017-12-29]

  • 1、新增Nutz执行器Sample示例项目;
  • 2、新增任务运行模式 "GLUE模式(NodeJS) ",支持NodeJS脚本任务;
  • 3、脚本任务Shell、Python和Nodejs等支持获取分片参数;
  • 4、失败重试,完整支持:调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态(新增失败重试状态返回值)时,也将会自动重试一次;
  • 5、失败告警策略扩展:默认提供邮件失败告警,可扩展短信等,扩展代码位置为 "JobFailMonitorHelper.failAlarm";
  • 6、执行器端口支持自动生成(小于等于0时),避免端口定义冲突;
  • 7、调度报表优化,支持时间区间筛选;
  • 8、Log组件支持输出异常栈信息,底层实现优化;
  • 9、告警邮件样式优化,调整为表格形式,邮件组件调整为commons-email简化邮件操作;
  • 10、项目依赖全量升级至较新稳定版本,如spring、jackson等等;
  • 11、任务日志,记录发起调度的机器信息;
  • 12、交互优化,如登陆注销;
  • 13、任务Cron长度扩展支持至128位,支持负责类型Cron设置;
  • 14、执行器地址录入交互优化,地址长度扩展支持至512位,支持大规模执行器集群配置;
  • 15、任务参数“IJobHandler.execute”入参改为“String params”,增强入参通用性。
  • 16、IJobHandler提供init/destroy方法,支持在相应任务线程初始化和销毁时进行附加操作;
  • 17、任务注解调整为 “@JobHandler”,与任务抽象接口统一;
  • 18、修复任务监控线程被耗时任务阻塞的问题;
  • 19、修复任务监控线程无法监控任务触发和执行状态均未0的问题;
  • 20、执行器动态代理对象,拦截非业务方法的执行;
  • 21、修复JobThread捕获Error错误不更新JobLog的问题;
  • 22、修复任务列表界面左侧菜单合并时样式错乱问题;
  • 23、调度中心项目日志配置改为xml文件格式;
  • 24、Log地址格式兼容,支持非"/"结尾路径配置;
  • 25、底层系统日志级别规范调整,清理遗留代码;
  • 26、建表SQL优化,支持同步创建制定编码的库和表;
  • 27、系统安全性优化,登陆Token写Cookie时进行MD5加密,同时Cookie启用HttpOnly;
  • 28、新增"任务ID"属性,移除"JobKey"属性,前者承担所有功能,方便后续增强任务依赖功能。
  • 29、任务循环依赖问题修复,避免子任务与父任务重复导致的调度死循环;
  • 30、任务列表新增筛选条件 "任务描述",快速检索任务;
  • 31、执行器Log文件定期清理功能:执行器新增配置项("xxl.job.executor.logretentiondays")日志保存天数,日志文件过期自动删除。

6.21 版本 V1.9.1 特性[2018-02-22]

  • 1、国际化:调度中心实现国际化,支持中文、英文两种语言,默认为中文。
  • 2、调度报表新增"运行中"中状态项;
  • 3、调度报表优化,报表SQL调优并且新增LocalCache缓存(缓存时间60s),提高大数据量下报表加载速度;
  • 4、修复打包部署时资源文件乱码问题;
  • 5、修复新版本chrome滚动到顶部失效问题;
  • 6、调度中心配置加载优化,取消对配置文件名的强依赖,支持加载磁盘配置;
  • 7、修复脚本任务Log文件未正常close的问题;
  • 8、项目依赖全量升级至较新稳定版本,如spring、jackson等等;

6.22 版本 V1.9.2 特性[2018-10-05]

  • 1、任务超时控制:新增任务属性 "任务超时时间",并支持自定义,任务运行超时将会主动中断任务;
  • 2、任务失败重试次数:新增任务属性 "失败重试次数",并支持自定义,当任务失败时将会按照预设的失败重试次数主动进行重试;同时收敛废弃其他失败重试策略,如调度失败、执行失败、状态码失败等;
  • 3、新增任务运行模式 "GLUE模式(PHP) ",支持php脚本任务;
  • 4、新增任务运行模式 "GLUE模式(PowerShell) ",支持PowerShell脚本任务;
  • 5、调度全异步处理:任务触发之后,推送到调度队列,多线程并发处理调度请求,提高任务调度速率的同时,避免因网络问题导致quartz调度线程阻塞的问题;
  • 6、执行器任务结果落盘优化:执行器回调失败时将任务结果写磁盘,待重启或网络恢复时重试回调任务结果,防止任务执行结果丢失;
  • 7、任务日志查询速度大幅提升:百万级别数据量搜索速度提升1000倍;
  • 8、调度中心提供API服务,支持通过API服务对任务进行查询、新增、更新、启停等操作;
  • 9、底层自研Log组件参数占位符改为"{}",并修复打印有参日志时参数不匹配导致报错的问题;
  • 10、任务回调结果优化,支持展示在Rolling log中,方便问题排查;
  • 11、底层LocalCache组件兼容性优化,支持jdk9、jdk10及以上版本编译部署;
  • 12、告警邮件固定使用 UTF-8 编码格式,修复由机器编码导致的邮件乱码问题;
  • 13、告警邮件中展示失败告警信息;
  • 14、告警邮箱支持SSL配置;
  • 15、Window机器下File.separator不兼容问题修复;
  • 16、脚本任务异常Log输出优化;
  • 17、任务线程停止变量修饰符优化;
  • 18、脚本任务Log文件流关闭优化;
  • 19、任务报表成功、失败和进行中统计问题修复;
  • 20、核心依赖Core内部国际化处理;
  • 21、默认Quartz线程数调整为50;
  • 22、新增左侧菜单"运行报表";
  • 23、执行器手动设置IP时取消绑定Host的操作,该IP仅供执行器注册使用;修复指定外网IP时无法绑定执行器Host的问题;
  • 24、取消父子任务不可重复的限制,支持循环任务触发等特殊场景;
  • 25、任务调度备注中标注任务触发类型,如Cron触发、父任务触发、API触发等等,方便排查调度日志;
  • 26、底层日志组件SimpleDateFormat线程安全问题修复;
  • 27、执行器通讯线程优化,corePoolSize从256降低至32;
  • 28、任务日志表状态字段类型优化;
  • 29、GLUE脚本文件自动清理功能,及时清理过期脚本文件;
  • 30、执行器注册方式切换优化,切换自动注册时主动同步在线机器,避免执行器为空的问题;
  • 31、跨平台:除了提供Java、Python、PHP等十来种任务模式之外,新增提供基于HTTP的任务模式;
  • 32、底层RPC序列化协议调整为hessian2;
  • 33、修复表字段 “t.order”与数据库关键字冲突查询失败的问题,
  • 34、任务属性枚举 "任务模式、阻塞策略" 国际化优化;
  • 35、分片任务失败重试优化,仅重试当前失败的分片;
  • 36、任务触发时支持动态传参,调度中心与API服务均提供提供动态参数功能;
  • 37、任务执行日志、调度日志字段类型调整,改为text类型并取消字数限制;
  • 38、GLUE任务脚本字段类型调整,改为mediumtext类型,提高GLUE长度上限;
  • 39、任务监控线程Log输出优化,运行中任务的监控Log改为debug级别,减少非核心日志量;
  • 40、项目依赖全量升级至较新稳定版本,如spring、Jackson、groovy等等;
  • 41、docker支持:调度中心提供 Dockerfile 方便快速构建docker镜像;

6.23 版本 V2.0.0 Release Notes[2018-11-04]

  • 1、调度中心迁移到 springboot;
  • 2、底层通讯组件迁移至 xxl-rpc;
  • 3、容器化:提供官方docker镜像,并实时更新推送dockerhub(docker pull xuxueli/xxl-job-admin),进一步实现产品开箱即用;
  • 4、新增无框架执行器Sample示例项目 "xxl-job-executor-sample-frameless"。不依赖第三方框架,只需main方法即可启动运行执行器;
  • 5、命令行任务:原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;
  • 6、任务状态优化,仅运行状态"NORMAL"任务关联至quartz,降低quartz底层数据存储与调度压力;
  • 7、任务状态规范:新增任务默认停止状态,任务更新时保持任务状态不变;
  • 8、IP获取逻辑优化,优先遍历网卡来获取可用IP;
  • 9、任务新增的API服务接口返回任务ID,方便调用方实用;
  • 10、组件化优化,移除对 spring 的依赖:非spring应用选用 "XxlJobExecutor" 、spring应用选用 "XxlJobSpringExecutor" 作为执行器组件;
  • 11、任务RollingLog展示逻辑优化,修复超时任务无法查看的问题;
  • 12、多项UI组件升级到最新版本,如:CodeMirror、Echarts、Jquery 等;
  • 13、项目依赖升级 groovy 至较新稳定版本;pom清理;
  • 14、子任务失败重试重试逻辑优化,子任务失败时将会按照其预设的失败重试次数主动进行重试

6.23 版本 v2.0.1 Release Notes[2018-11-09]

  • 1、左侧菜单折叠动画问题修复;
  • 2、调度报表日期分布图默认值统一;
  • 3、freemarker对数字默认加千分位问题修复,解决日志ID被分隔导致查看日志失败问题;
  • 4、底层通讯组件升级,修复通讯异常时无效等待的问题;
  • 5、执行器启动之后jetty停止的问题修复;

6.24 版本 v2.0.2 Release Notes[迭代中]

  • 1、调度中心告警邮件发送组件改为 “spring-boot-starter-mail”;
  • 2、任务告警逻辑调整,改为通过扫描失败日志方式触发。一方面精确扫描失败任务,降低扫描范围;另一方面取消内存队列,降低线程内存消耗;

TODO LIST

  • 1、任务分片路由:分片采用一致性Hash算法计算出尽量稳定的分片顺序,即使注册机器存在波动也不会引起分批分片顺序大的波动;目前采用IP自然排序,可以满足需求,待定;
  • 2、任务单机多线程:提升任务单机并行处理能力;
  • 3、任务依赖,流程图,子任务+会签任务,各节点日志;
  • 4、调度任务优先级;
  • 5、移除quartz依赖,重写调度模块:新增或恢复任务时将下次执行记录插入delayqueue,调度中心集群竞争分布式锁,成功节点批量加载到期delayqueue数据,批量执行。
  • 6、多数据库支持,在重写并移除Quartz的基础上,DAO层通过JPA实现,不限制数据库类型;
  • 7、执行器Log清理功能:调度中心Log删除时同步删除执行器中的Log文件;
  • 8、Bean模式任务,JobHandler自动从执行器中查询展示为下拉框,选择后自动填充任务名称等属性;
  • 9、API事件触发类型任务(更类似MQ消息)支持"动态传参、延时消费";该类型任务不走Quartz,单独建立MQ消息表,调度中心竞争触发;待定,该功能与 XXL-MQ 冲突,该场景建议用后者;
  • 10、调度线程池改为协程方式实现,大幅降低系统内存消耗;
  • 11、任务依赖增强,新增任务类型 "流程任务",流程节点可挂载普通类型任务,承担任务依赖功能。现有子任务模型取消;需要考虑任务依赖死循环问题;
  • 12、提供多版本执行器:不依赖容器版本、不内嵌Jetty版本(通过配置executoraddress替换jetty通讯)等;
  • 13、注册中心支持扩展,除默认基于DB之外,支持扩展接入第三方注册中心如zk、eureka等;
  • 14、流程任务,支持参数传递;
  • 15、Cron TimeZone 自定义;
  • 16、忙碌转移优化,全部机器忙碌时不再直接失败;
  • 17、流程任务等,透传动态参数;
  • 18、任务支持切换执行器,quartz job group固定;
  • 19、任务自动注册;待考虑,因为任务自动注册将会导致任务难以管理控制;
  • 20、批量触发支持,添加参数 "org.quartz.scheduler.batchTriggerAcquisitionMaxCount: 50";
  • 21、失败重试间隔;
  • 22、任务权限管理:执行器为粒度分配权限,核心操作校验权限;
  • 23、SimpleTrigger 支持;
  • 24、cron在线生成工具,如 "cronboot/cron.qqe2";
  • 25、调度日志列表加上执行时长列,并支持排序;

七、其他

7.1 项目贡献

欢迎参与项目贡献!比如提交PR修复一个bug,或者新建 Issue 讨论新特性或者变更。

7.2 用户接入登记

更多接入的公司,欢迎在 登记地址 登记,登记仅仅为了产品推广。

7.3 开源协议和版权

产品开源免费,并且将持续提供免费的社区技术支持。个人或企业内部可自由的接入和使用。

  • Licensed under the GNU General Public License (GPL) v3.
  • Copyright (c) 2015-present, xuxueli.

捐赠

无论捐赠金额多少都足够表达您这份心意,非常感谢 :) 前往捐赠

]]>
taoCMS-基于php+sqlite最小巧的CMS 2019-02-08 01:02:10
1161 郭鹤年自传的读后感

  《郭鹤年自传》读后感(一):一位长者真实人生

  95岁高龄的郭鹤年先生是个很敢讲真话的人,这本书给我最大的感觉是“实在”。

  不似职业作家成功人士写的传记,为了引人眼球,往往视角有所偏颇;也不似那些正当盛年的企业家写的自传,对于创业过程中某些关键隐秘细节遮遮掩掩。

  读郭先生写这本书,真的仿佛一位慈眉善目的敦厚长者在眼前,耳提面命地跟你叙述“我是怎样一步步走向成功的”。无论是在日企的第一份工作利用职务之便“赚黑钱”,还是创业时因受银行羞辱产生进取心,甚至是特殊时期通过香港中粮子公司与国资合作的细节,都事无巨细地呈现在这本书里。

  郭先生的父亲是个教育程度不高的大商人,虽然郭先生不很喜欢这位时常打骂他们母子的父亲,但毋庸置疑,郭先生最初的商业头脑跟从小的耳濡目染及在父亲公司的三年历练关系很大。郭先生的母亲是位修养极好的善良女性,如郭先生自己所说,自己性格中善良、正直等等高尚特质主要受母亲影响

  “性格决定命运”。郭先生同时继承了父亲在商业上的精明和母亲在人格上的正直,这显然为他日后成就事业奠定了基础

  书中印象最深的有这样两段话:

  第一个细节是在61页。郭先生说:“我一生坚信,忙碌是一种治疗。一个有工作的人会比别人早期,晚上又因为需要回复体力而比别人早睡,这样便不会浪费生命感谢上帝,庆幸我们那时没有电视、没有愚蠢电子游戏、没有现在报摊上那些琳琅满目的恶俗杂志,那都只是为了迎合人类低下庸俗本质。”

  第二个细节在89页。郭先生说:“在商界,我只是一个初出茅庐小伙子,一切都得从头学起。没有人教过我,但我人生中所做的每一件事情,每一个举动,都是一次学习的过程。如果我不是忙于做这些事,我那活跃大脑精力充沛身体也会把我推向其他方面。我总觉得智慧就在我们身边,俯拾皆是。能有系统地学习固然是好,但其实只要你愿意学习,你便能如呼吸一样,萃取到智慧。”

  从这两个细节,可以看出郭先生成功的两个极重要的特质,始终如一勤奋谦逊好学的开放心态

  除此之外,也可以看出这本自传的风格。郭先生在将自己一生的故事娓娓道来的同时,更把自己认为重要的事件感受,不断进行强调,生怕读者错过

  至于郭先生的成功,究竟是个人性格使然,还是方兴未艾时代的造就,我想,每个人在读完了书后心里都有自己的答案

  无论如何,我想,这本书是值得再读一遍的。

  《郭鹤年自传》读后感(二):为什么说《郭鹤年自传》是是世界富豪少有的自传?

  马来西亚首富郭鹤年口述、资深财经记者Andrew Tanzer撰写的《郭鹤年自传》(英文版新加坡Landmark出版,中文版香港商务出版),甫一面世,便引起全球媒体关注

  因为郭鹤年在自传中的爆料内容,涉及不少国家级和国际级的政经秘辛,在马来西亚和新加坡引起广泛的讨论舆论为郭鹤年在世界政经领域身份地位却愿意当一个爆料者而称奇,也为他在跨度近一个世纪历史中的详尽记忆惊讶

  《郭鹤年自传》是世界级富豪少有的自传,并不避讳写出自己的致富之道,透露商场竞争激烈过程,也写出自己的心路历程

  这位九十四岁的百亿富豪并不打算留下一本平平无奇、四平八稳如庭训一般的回忆录子孙,而是写出他一生经历思索得出的大量对政治经济经营等等见解,不但有成功心得,也包含失败挫折乃至自己犯下的错误教训,甚至是许多名人隐之而不及的家族私密

  这位纵横四海企业家,坦荡作风与不畏权势后果魄力,或许正是他一贯作风,也加倍增添了本书的可读性。

  郭鹤年一九二三年生在马来亚南端的新山,与新加坡一衣带水,父亲做小生意很快赚了不少钱但不会理财,他童年遇到大萧条和二次大战,家道中落。二十几岁时,他靠着在伦敦的食糖市场赚到第一桶金,随后在马来亚开设糖厂、面粉厂等等,发迹成为东南亚富豪,并且移居新加坡,后来又为了税务较低而移居香港。

  他比马来西亚与新加坡甚至东南亚许多政经界领袖长寿,也与他们共同经历将近一个世纪的历史发展,期间还参与不少事务,他的回忆录因此变得情节丰富,而他的直言不讳,更使得本书具有震撼性的历史意义,读者仿佛看见在一些关键时刻,历史如何受到扭曲,而他如何在其间奋斗求存。

  生长于英殖民时期的马来亚,少年时期马来亚被日本侵占,使得郭鹤年萌生浓浓的反殖情怀

  六十年代初他在伦敦从事食糖生意,与英国糖业贸易商嘉利高(C. Czarnikow)的高层会面,那位高层以教训的语气反对他在大马建糖厂,让他觉得英国殖民主义和垄断思想在那个年代仍然阴魂不散。

  他早年也曾面对英资银行的种族歧视,说他们宁愿贷款给拾荒的白种人,也不考虑贷款给正当的本地商人,“肤色决定一切”。他还记得当一家英资洋行的收款单上赫然印着:“欧洲职员签署后,收据方为有效”。

  郭鹤年认为,殖民主义是人类最大的祸根之一,对加害者和被殖民者皆如是。“英国公务员十个当中有九个都是好人,无论在学校教书或在路上遇见他们时,均表现如常,十分友善。但当他们走进专属的俱乐部或谈生意时,却仿佛变成了另一个人。”

  二战时期郭鹤年曾任职日资三井公司,但他对日本占领军的残暴不满,战后他发现,日本虽战败,但日商负责人仍然以殖民主义者嘴脸对待他。

  综观自传的叙述,郭鹤年的出生地马来亚从殖民时期到独立后,都不幸地笼罩着浓浓的种族情结,始终走不出来,英国人带着种族歧视的心态统治殖民地,而全书批判严厉的,也正是他对马来西亚在独立后进一步走向种族保护主义的痛心

  一九六九年五月十三日马来西亚爆发“五一三暴动”,上千华人被打死,已经移居新加坡的郭鹤年刚好回吉隆坡开会,目睹暴徒四处火烧楼的疯狂行径。他感叹马来西亚独立建国之初的一代领袖,如国父东姑阿都拉曼、敦拉萨、敦伊斯迈,“都是很优秀的人,深爱并关心自己的国家和人民”,这些他所熟悉的领袖并没有太强的种族偏见,因此执政联盟中,无论是巫统或马华公会找他作大笔捐款,他“总是心甘情愿愉快大方地给与捐助”。

  他特别提到东姑虽然具有人情味,会帮助朋友,但“从不利裙带关系”,他有一次为朋友写信给财政部长陈修信,请求帮忙宽赦税务问题,陈修信为此大怒,把信拿去给敦伊斯迈医生看,说“你看看首相对我做了什么”,后者笑着把信揉成一团丢进垃圾桶,事情就结束了。郭鹤年说:“这是东姑帮朋友的极限。”

  不少大马读者不免感慨,相对于后来的政治,那还真是清明的时代呀。

  郭鹤年以诸如此类事例说明当时许多建国者都怀抱热情使命感。因此他紧接着写道:“任人唯亲者则完全不同,他们都是阿谀奉承之徒,把领导人吹捧得膨胀自大领导人便拿国家利益分配给他们。一个国家的财产项目和生意是绝不容许任何人将之配送的。”

  他说:“任人唯亲的领导会以加快振兴国家为借口,来掩饰他的所作所为。他会摈弃所有基本原则,如无视公务员规章,简单直接地把项目交给某个华裔或马来裔亲信。国有银行被逼贷款给这些项目,一些亲信甚至为贪官污吏撑腰。”

  郭鹤年指出,虽然在英国人时代已经给予马来人一些优惠,马来亚一九五七年独立后也延续这些优惠,但并没有过度的偏袒与倾斜。然而五一三事件却对马来西亚的体制造成巨大冲击。一些长期以“马来人地位低下受华人印度人压迫”为诉求的马来极端分子进一步在政治上挤压东姑等温和与开明派领袖。

  五一三之后,郭鹤年看到马来西亚商界开始发生变化。在此之前,他为了协助国家发展,应政府要求走入船运业,开设钢铁厂,在借助华人力量的过程中,马来领袖大致表现公道。然而五一三之后,马来领袖剩下一个逻辑:“马来人需要援助”。

  一九七一年,第二任首相敦拉萨(现任首相纳吉之父)启动一项为期二十年的“新经济政策”,目的是希望在二十年内缩小马来土著与华人之间的经济差距

  国家部门下令非马来人开设公司,必须把百分之三十股份出售给马来人,并且是要求低于当时的市值,但马来人在获得配股之后,过了一段时间就会把股份套利,在华人买回来后,过几年再查访股份结构,发现马来人持股又低于百分之三十,又会要求再配股给马来人。

  郭鹤年质问,这无疑是强盗行为:“难道有政府认可,就不算是抢掠吗?”他说,马来人急于缩小与华裔之间的经济鸿沟,却走了有害捷径副作用则是种族主义越演越烈。

  为此,一九七五年,敦拉萨病危,副首相胡申翁接班在即,郭鹤年甘冒大不韪去见这位老朋友兼老同学。书中详细描述两人见面的过程,郭鹤年谨慎地陈述他的观点,希望胡申翁接班之后,以人格、才干和勤奋程度三大素质作为用人原则,而不是种族和宗教

  他以恳求的口吻对胡申翁说:“请你选用聪明的人,心存正道的人,那些正直、有才干、勤奋、坚毅不屈的马来西亚人,不论种族、肤色和信仰,任用他们。”“这就是我们国家未来的简单方程式”。

  胡申翁全程几乎没有出声地聆听,然后静默了几分钟,说“我做不到”。

  书中毫不掩饰郭鹤年对这一局面失望与痛心,他形容自己看到的景象,仿佛一列火车朝着错误的方向行驶,胡申翁没有足够力量去举起火车放回正轨。那是这位商业奇才唯一一次试图去影响马来西亚历史进程努力

  马来西亚领袖除了早期央求郭鹤年协助建设一些大型国家企业,也找他作为与中国之间的传话人。

  01

  香港改变了郭鹤年

  一九八零年代,马国政治部请他转达中国,停止马共的广播,并且以书面保证停止支持马共及其领袖陈平,郭鹤年当时已是亿万富豪,却毅然只身奔走,终于促成马国政府与陈平签署和平协议,马共走出丛林。书中有精采描述。

  郭鹤年在这事件中也不无特殊情感,因为他的一位哥哥郭鹤龄便是马共成员,五十年代在丛林中死于英军枪下。

  郭鹤年成年后把公司和家安在新加坡而不是新山,因为新加坡是国际商港,资讯流通,但他在七零年代移居香港,则是因为新马两国对企业征收的税率近乎惩罚性而且极其严苛,赚一元基本上只能剩下五毛钱,甚至让他觉得税务审计“有点像宗教裁判所”。而相比之下,当时香港的营业税只有百分之十七。

  搬去香港以后,相比于新加坡,那又是更开阔环境。他形容,全世界大公司的首席执行官每年都会去香港,资深副总裁会去新加坡,副总裁或部门经理则去吉隆坡,这是当时国际企业界的次序,而今天,首席执行官会去北京和上海。

  移居香港改变了郭鹤年的事业家庭,他毫不遮掩地向读者交代他在香港爱上现在的妻子何宝莲,为此他大哥、老同学和母亲都曾责怪他。元配谢碧蓉在获知之后经过一番深思,不愿离婚,慨然接受现状,“准备好与另一个女人一起拥有”,于是他就有了两头家。

  七十年代在香港,郭鹤年最早的重要投资就是九龙香格里拉大酒店,之后就连续在香港大兴土木,并接着进入大陆

  02

  兴建北京国贸的挫折

  在大陆初期经历了上有政策下有对策等等碰壁和打击,包括兴建北京国贸中心项目过程中的波折阻碍,他都仔细描述,并归纳出心得与读者分享

  在香港和大陆的发展过程中,一个大危机是二零零三年的非典型肺炎爆发,当时港岛香格里拉酒店的入住率曾经只有百分之二。媒体充斥各家企业紧缩业务裁员的消息,但他拒绝考虑,因为那无异于将员工遗弃在沙漠里。

  有趣的是,就在往建筑业越做越大的时候,郭鹤年才想起年轻时在马来西亚新山的家,还在从事种植和面粉加工业,没想过做房地产,有一天碰上一个印度人,看了他手掌就不断告诉他,“你会盖很多很多房子,不停地盖房子”。

  自传也爆出郭鹤年与印尼富商林绍良之间的生意恩怨

  郭表示在林的邀请下合作生意,因为有感印尼市场庞大,因此从七十年代开始二十几年间,出钱却没有一纸协议,投资了全球最大面粉加工厂,但大股东是林绍良,运营好几年后才开始分红,却不如他预期比例

  郭鹤年说:“我常常有被林氏坑骗的感觉,他们总是拿印尼政府做借口,甚至不用提‘政府’两字,一开口就说这是国父(苏哈图)的想法。林绍良为人较公道,尤其是对我,但他的三儿子林逢生长大后则不然。”他叙述事件到后来,甚至说出“林逢生试图设计欺骗我”。

  而在印尼拓展业务过程中,他也认识了苏哈图,后者则是在划出地段发展时,示意企业家让他自己的子女加入成为合伙人。

  虽然是郭鹤年的传记,但贯穿全书的灵魂人物是他的母亲郑格如。这位出身福州的闺秀年轻时被父母从大学里中断学业,盲目到南洋嫁给一个陌生人,才发现丈夫又吸鸦片又好赌,性格也不合,后来又有外遇。

  郭鹤年不停强调母亲对他人格的影响,直到他中年以后,一旦有生活和业务上的疑惑,都会去请教母亲,而母亲总能在言语和思考中,以及从佛理上,为他找到解答的路径。母亲的教育让他在商业和公司管理上建立严谨的道德原则,也让他从小对中国和中国文化产生亲切感。

  母亲晚年笃信佛教,常根据中文报章报道的社会悲惨和苦难者新闻,拿着剪报要公司助理去捐钱,并且要求匿名。郭鹤年这段叙述猛然令人想起新加坡报社早年经常收到一位“无名氏”的捐款。从来没有人知道那是谁。

  郭鹤年虽然是在马来亚出生,却有很深的中国情怀。

  文革期间中国大陆严重缺糖,派人秘密与他接触,希望透过国际商品市场进口,基于对中国的感情,郭鹤年开始一连串的部署,避免引起国际市场注意,私底下在全球食糖市场调兵遣将,不但解决了问题,还为中国赚取了一笔外汇。

  03

  难忘与邓小平见面

  郭鹤年也曾与几代中国领导人见面,包括邓小平、江泽民、胡锦涛与习近平。

  他在一九九零年九月十五日在北京与邓小平会面,是邓小平最后一次的公开正式会晤。邓小平当时说:“三十年后,中国将会成为亚洲最重要、最强大的国家,而亚洲将成为全球最强大的地区。”

  郭记忆犹新,并指邓说这话时很谦逊。在他印象中,邓小平是一位善良、友好、无私的人。但当邓谈到台湾问题时,郭第一次看见他带着一丝极度的挫败感。对于习近平,郭鹤年则称许他的反贪腐。不过,他指出,中国现正面对的两个最大挑战,分别是恢复道德教育与确立法治。

  郭鹤年具有非常浓厚的商人性格,经商手段快、狠、准,做事勤奋果断,对下属异常严厉,但采取把股份与下属共享的方式,而赢得下属的忠心。

  他懂多国语言,包括英语、马来语、华语、福州话、闽南话、潮州话、广东话,有助他与不同的人打交道,建立人脉。读英校的他,凭着娴熟的英文,六十年代初在伦敦打入商品交易商圈子,并了解英国商人的行事风格,借此掌握行情资讯,在国际糖期货市场大赚,奠定“糖王”地位。

  纵横商场七八十年,足迹遍布全球,郭鹤年的经历当世已经没几个人能比。

  三百多页的自传显然远远不足以涵盖他精采的一生,但已经令人手不释卷。他坦率与诚恳的自剖,还有对文化、企业经营、人才、资本主义乃至金钱价值等等观念的系统性看法,简洁而切入要害,引人深思,让本书有不同于一般传记的阅读价值。

  04

  郭鹤年小档案

  1923年生于马来西亚柔佛州新山,祖籍福建福州。曾就读新加坡莱佛士书院。

  从事米粮及糖生意起家,1949年在马来西亚成立郭氏兄弟集团,六十年代在伦敦糖期货市场赚到第一桶金,有“糖王”之称。七十年代赴香港,以香港为基地,成立嘉里集团,并在八十年代进军中国大陆。旗下主要企业包括香格里拉酒店、嘉里地产、丰益国际(经营商品贸易、油棕种植及食用油生产等)等。

  为大马首富,在福布斯全球富豪排行榜中排名115,净资产139亿美元。元配谢碧蓉已逝,育有二子三女;现妻何宝莲,育有一子二女。他有两个哥哥,大哥郭鹤举是大马外交官,二哥郭鹤龄是马来亚共产党成员,1952年紧急状态时被杀。

  来源:亚洲周刊

  《郭鹤年自传》读后感(三):抓住时代

  大概是周三拿到此书,郭鹤年先生口述,一个外国记者编著,回忆了一生的经历。颇巧合的是周五另一个华商大佬宣布休息,或许大家对李嘉诚比较熟悉,但对郭鹤郭鹤年先生年了解不多,通过本书,增加对郭鹤年郭鹤年先生及其商业帝国了解,从中得到启示。 本书是口语化写作,全部看完不过10小时左右。早先几乎都没听说过郭鹤年先生,虽然我们食用的金龙鱼食用油以其益海嘉里经常在电视广告上看到,然而农产品也只是其商业版图的一部分。 本书首先回顾了郭鹤年先生从小马来西亚柔佛新山出生,此时正值英国统治时期,随后日军侵犯。马来西亚独立后,在食糖市场赚到第一桶金,开办炼糖场,面粉厂等等。有时帮助政府管理一些发展国民经理的企业。也借助在政府的人脉关系,在各个市场上开办贸易并取得成功。 农产品贸易之后是酒店开发,地产等等。

  后半部分回忆了参与中国的改革开放建设,也分享了一些商业感悟。

  ------------

  书是好书,推荐一看,太累了,不想写太多了。

  《郭鹤年自传》读后感(四):一生涓滴意念,汇聚成江湖

  说不定我一生涓滴意念 侥幸汇成河

  ……

  因为不安而频频回首无知地索求 羞耻于求救不知疲倦地翻越

  ……

  ——『山丘』

  郭鹤年先生一手创建郭氏集团,旗下生意庞大,知名品牌“香格里拉”“金龙鱼”“嘉里中心”相伴我们的生活。他自传相当值得看。 他展现了直率,在这本出版于17年底的自传中毫不避讳政商关系,分享他的家国情怀,他对时政的观点,与政治领袖打交道的情况。 所以无论你是八卦也好,或者想汲取经商之道,抱着这样的目的需求,都可以从这本郭鹤年的自传有所收获。 郭先生的经商史有如一片宽阔海洋。70余载经商,历经二战、东南亚殖民地独立期,中国的改革开放早期。 他的事业地理范围辽阔,从马来西亚的柔佛新山,到荟聚亚太的明珠新加坡,到璀璨中华的眺望所香港,再到瞩目的新世界北京上海,这些亚洲城市,是亚洲经济发展的汇聚点,稍有遗憾的是郭的事业未涉足东亚的日韩。 郭是最早跟中国做生意打交道的商人,也是改革开放早期最早对大陆下重注的华侨。邓小平同志人生最后一个外事活动是接见郭鹤年,对以郭为代表的华侨及海外同胞对祖国建设的倾力支持表达感谢。 郭在这本自传中对改革开放初期,投资祖国大陆的经历有很详细的阐述,其中郭个人的心路历程描述细致,娓娓道来。 多元化事业的成功经营,郭先生摘要记录,其中特别是自己早期的经商活动。历经艰辛,辗转东西,打造大米、食糖生意。这期间,他的敏锐的商业视角,营商的韬略,与欧洲人打交道的能力,自传中均有细致阐述。 早年的历史、生意经营的跌宕起伏经历,对生意伙伴、同行的评述,郭先生超强的记忆力几乎不得不让你肃然起敬。 对于事业起步期的经历,郭先生毫不避讳。郭在二战期间,帮日本人做生意,并且“吃里扒外”,经营自己的外快。这段历史,他看到了军事、政治与经济的紧密交织的关系。但郭在自传中对后期的生意,可能因为还在经营的缘故,反而涉及不多。稍有遗憾。 从事业的宽度与生意的长度看,他的生意多元却均闪耀成功光环。无论是亚洲糖王,还是酒店大王,或者是粮油大王,他在多个领域取得成功。这些成功,是时势造英雄,更是商业英雄踩准了时代发展的点位,同步疾行。 郭先生也不避讳跟马来西亚、印尼总统的交往。郭的生意涉足民生行业(大米、糖、面粉、食用油),涉及土地地产(香格里拉酒店、嘉里中心),涉及国计行业(船舶),郭先生对商业跟政治密不可分的关系,明确定论。 郭亦提及自己充当中国大陆与印尼沟通桥梁的历史;这些都具有很强的时代印记。他还提及印尼国内的反华潮这段历史。有一个章节,是他与印尼即将接任总理的老同学的对话,郭的描述犹如一部精彩的史诗电影,自传中郭记录的对话,写实感强,历史从未这么形象生动予以呈现。 他亦补充专章提及现今中国的舵手,评价非常高。 如果只是以上这些记录,那这本自传最多算是精彩,最多是拥有历史厚重感,最多是有商人的成功经商经验;我认为这本书最出彩的部分是,字里行间透露的文化的家教传承。 你去看,当有非常重大事项要做决策时,郭哪怕心里已有决定,但他会求助了自己的母亲,询问母亲的意见,他遵循的是中国的传统的孝道; 你去看,郭对早年生活的记忆,他对母亲面对家庭变故的行动,母亲遇事后的言传身教,郭的血液里浇灌了中国女性高尚、坚韧不拔的家教; 你去看,郭记录早年被母亲痛打的记忆,记录早年兄弟关系,郭从小学会了为人处世之道。 这些文化至柔部分,跟郭骨子里的经商天分、对商业世界的观察思考、勤奋拼搏这些刚强结合,刚柔并济,共同塑造了郭鹤年这位横跨东南亚的商业巨子。 我们都身处这个充满危与机的时代,为何是郭鹤年、李嘉诚等这样的人走了出来?郭鹤年的经历,既有时代的因素,更多是他自己的积累。这部自传,相信会给我们很多启发和思考。 所以,与其说郭的成功史,是一部厚重的东南亚华裔的奋斗史,一部商人的经商史,不如说是个人的奋斗史、成长史,也是华人社会的文化社会学著作。 所以推荐这本郭鹤年自传。


]]>
taoCMS-基于php+sqlite最小巧的CMS 2018-12-14 01:12:36
1160 如何发家致富(不靠运气) How to Get Rich (without getting lucky):
  • 寻求财富,而不是钱或者身份。财富是拥有资产,睡觉时都能挣钱。钱是我们用来转移时间和财富的东西。身份是你的社会地位。

    Seek wealth, not money or status. Wealth is having assets that earn while you sleep. Money is how we transfer time and wealth. Status is your place in the social hierarchy.
  • 理解“君子爱财取之有道”是可以做到的。如果你暗自蔑视财富,财富就会躲着你。

    Understand that ethical wealth creation is possible. If you secretly despise wealth, it will elude you.
  • 忽视那些玩身份游戏的人。他们通过攻击玩财富创造游戏的人来获得“身份”。

    Ignore people playing status games. They gain status by attacking people playing wealth creation games.
  • 出租时间无法变得富有。你必须拥有资产 —— 生意的一部分 —— 来收获财务自由。

    You’re not going to get rich renting out your time. You must own equity - a piece of a business - to gain your financial freedom.
  • 提供社会想要得到、但不知如何得到的东西。规模化后,你就会变得富有。

    You will get rich by giving society what it wants but does not yet know how to get. At scale.
  • 选择可持续发展的行业,和可持续的伙伴一起玩。

    Pick an industry where you can play long term games with long term people.
  • 互联网已经大量地拓宽了职业空间。大部分人还没有理解这一点。

    The Internet has massively broadened the possible space of careers. Most people haven't figured this out yet.
  • 玩反复的游戏。无论是财富,关系还是知识,生活中所有的回报都来自于复利。

    Play iterated games. All the returns in life, whether in wealth, relationships, or knowledge, come from compound interest.
  • 选择高度聪明,有能量的,以及正直这一高于所有其它因素的人,作为商业伙伴。

    Pick business partners with high intelligence, energy, and, above all, integrity.
  • 不要和愤世嫉俗者以及悲观主义者合作,他们的信念会自我实现。

    Don't partner with cynics and pessimists. Their beliefs are self-fulfilling.
  • 学习销售,学习创建。如果两个你都能做,你是不可阻挡的。

    Learn to sell. Learn to build. If you can do both, you will be unstoppable.
  • 用特种知识,责任和影响力武装你自己。

    Arm yourself with specific knowledge, accountability, and leverage.
  • 无法通过培训获得特种知识。如果社会可以培训你,就也可以培训其他人,然后取代你。

    Specific knowledge is knowledge that you cannot be trained for. If society can train you, it can train someone else, and replace you.
  • 通过追逐真正的好奇心和激情获得特种知识,而不是通过追逐风口。

    Specific knowledge is found by pursuing your genuine curiosity and passion rather than whatever is hot right now.
  • 学习特种知识像玩游戏,但对其他人而言看上去像是工作。

    Building specific knowledge will feel like play to you but will look like work to others.
  • 当被教到特种知识的时候,是通过学徒制,而不是在学校。

    When specific knowledge is taught, it’s through apprenticeships, not schools.
  • 特种知识通常是高度技术性或者创造性的,它不能被外包或者自动化。

    Specific knowledge is often highly technical or creative. It cannot be outsourced or automated.
  • 拥抱责任,以自己名义承担商业风险。社会会奖励你权责、公平和影响力。

    Embrace accountability, and take business risks under your own name. Society will reward you with responsibility, equity, and leverage.
  • 最负责的人有着奇异的,公开的,冒险性的品牌:奥普拉,川普,凯恩,马斯克

    The most accountable people have singular, public, and risky brands: Oprah, Trump, Kanye, Elon.
  • “给我一个足够长的杠杆,一个立足之地,我就可以撬动地球” —— 阿基米德

    “Give me a lever long enough, and a place to stand, and I will move the earth.” - Archimedes
  • 财富需要杠杆,商业杠杆来自于资本、人力、没有边际成本的复制品(代码和媒体)。

    Fortunes require leverage. Business leverage comes from capital, people, and products with no marginal cost of replication (code and media).
  • 资本指的是钱。用上你的特种知识,承担责任,并展示出好的判断力来融资。

    Capital means money. To raise money, apply your specific knowledge, with accountability, and show resulting good judgment.
  • 劳动力是替你干活的人。这是最古老的,以及最具争议的杠杆形式。劳动力杠杆会让你父母留下深刻印象,但是不要浪费你的生命来追逐它。

    Labor means people working for you. It's the oldest and most fought-over form of leverage. Labor leverage will impress your parents, but don’t waste your life chasing it.
  • 资本和劳动力是需要许可的杠杆。每个人都在追逐资本,但是需要某些人给你。每个人都在尝试领导他人,但是需要有人来追随你。

    Capital and labor are permissioned leverage. Everyone is chasing capital, but someone has to give it to you. Everyone is trying to lead, but someone has to follow you.
  • 代码和媒体是无需许可的杠杆。它们是新富们背后的杠杆。创造出来的软件和媒体一直在运作,哪怕你还在睡觉。

    Code and media are permissionless leverage. They're the leverage behind the newly rich. You can create software and media that works for you while you sleep.
  • 有一个机器人大军可以自由得到 —— 它只是因为热力和空间效率的问题被打包在数据中心里了,用起来。

    An army of robots is freely available - it's just packed in data centers for heat and space efficiency. Use it.
  • 如果不会写代码,就去写书和博客,录视频和播客。

    If you can't code, write books and blogs, record videos and podcasts.
  • 影响力是你的判断力的力量乘数。

    Leverage is a force multiplier for your judgement.
  • 判断力需要经验,但是可以通过学习基础技能更快地建立。

    Judgement requires experience, but can be built faster by learning foundational skills.
  • 没有一种技能叫做“商业”,避开商业杂志和商业课程。

    There is no skill called “business.” Avoid business magazines and business classes.
  • 学习微观经济学,博弈论,心理学,说服力,伦理学,数学以及计算机。

    Study microeconomics, game theory, psychology, persuasion, ethics, mathematics, and computers.
  • 阅读比聆听更快,执行比观望更快。

    Reading is faster than listening. Doing is faster than watching.
  • 你应该忙得连“喝个咖啡”的时间也没有,但不要让日程表变成碎片时间。

    You should be too busy to “do coffee," while still keeping an uncluttered calendar.
  • 设立并强制实施一个乐观的个人时薪,也就是你每小时的工资。如果解决问题省下的钱低于时薪,就忽视问题。如果外包任务的成本低于时薪,那就外包。

    Set and enforce an aspirational personal hourly rate. If fixing a problem will save less than your hourly rate, ignore it. If outsourcing a task will cost less than your hourly rate, outsource it.
  • 尽你所能,努力工作。虽然,工作的同事、工作的内容比努力更重要。

    Work as hard as you can. Even though who you work with and what you work on are more important than how hard you work.
  • 在你所做的领域内做到世界一流,持续重新定义你所做的工作,直到成为事实。

    Become the best in the world at what you do. Keep redefining what you do until this is true.
  • 没有快速致富的方案,那种方案只是让别人从你身上发财。

    There are no get rich quick schemes. That's just someone else getting rich off you.
  • 通过杠杆应用你的特种知识,最终你会得到你所应得的。

    Apply specific knowledge, with leverage, and eventually you will get what you deserve.
  • 当你最终变得富有,就意识到这不是一开始所努力的方向。但那已非今日。

    When you're finally wealthy, you'll realize that it wasn't what you were seeking in the first place. But that's for another day.
  • ]]>
    taoCMS-基于php+sqlite最小巧的CMS 2018-12-09 19:12:33
    1159 洛克菲勒的十条习惯 洛克菲勒大家都知道,下面一小段话对于洛克菲勒的介绍:

    约翰·戴维森·洛克菲勒 (John Davison Rockefeller) (1839年7月8日–1937年5月2日),出生于美国纽约州里奇福德,美国慈善家、资本家。1870年他创立了标准石油,垄断了全美90%的石油市场,成为美国第一位10亿美元富豪与全球首富。他也普遍被视为人类近代史上首富,财富总值折合今日之3000亿美元以上。

    更令人称道的不是上面这些,而是到现在一百多年的时间,洛克菲勒家族依然非常辉煌,完全没有中国常说的富不过三代的情况发生。

    咨询公司 In-Synk 的博客上曾经评价:「现今任何一位商界巨擘的身家甚至都无法与其当年相提并论。如果根据通货膨胀调整资产,在洛克菲勒和他的标准石油面前,比尔盖茨的微软、巴菲特的伯克希尔·哈撒韦、乔布斯的苹果公司皆会黯然失色。」

    洛克菲勒不仅个人在商业上取得巨大的成功,其家族也绵延持续发展,他的子孙继承了他的事业。洛克菲勒家族成了美国10大超级富豪之一,也是当今美国最负盛名的家族之一。他的孙子纳尔逊·洛克菲勒曾当上了美国副总统,而他的另一个孙子大卫·洛克菲勒,则是赫赫有名的大银行家。

    也就是说无论是商业、子女教育和财富传承,为什么洛克菲勒能持续的取得一个又一个成功?而今天的年轻人,今天的企业,又能从洛克菲勒身上学到什么?

    通过最近一段时间的研究发现,「洛克菲勒习惯」(THE ROCKEFELLER HABITS)是一个非常核心的精神遗产,理解,掌握并运用「洛克菲勒习惯」,不仅能帮助你在工作中取得非常好的业绩,也能帮助整个项目组的成员都在工作满意度上大幅提高。同时,通过学习和实践洛克菲勒习惯,本身就是一种「管理学」的学习和实践。而相比于传统意义上的MBA课程,洛克菲勒习惯可以说是即学即用,非常了得。

    另外,当你通读洛克菲勒习惯,你会发现,很多习惯也可以在家庭教育中传承下去。也许,洛克菲勒家族财富的传承和持续发展,和洛克菲勒习惯本身也是关系密切。


    洛克菲勒的10条习惯


    1. 团队合作——执行团队健康且密切合作:彼此了解,(每周)定期见面,(每月)持续培训,团队讨论氛围融洽,有建设性。

    2. 任务分配——每人会被分配1项任务,需在本季度完成,以推动公司发展:确定支持这个任务的关键事项,确定优先级,季度主题和庆祝/奖励,通告进展。

    3. 日站会——建立沟通机制并且让信息能够准确快速地在组织内传递。(每天15分钟站会,每周周会,每月月会学习和讨论,每个季度末和年中,中高层 offsite (脱岗) 讨论人才、战略、执行和现金流)。(PS.每日站会指的是,日站会只开15分钟,并且所有人站着说。我个人的理解是站着有助于集中精力,并且缩短时间)

    4. 职能责任——组织的方方面面都要有专人负责,以确保实现目标:制定职能责任表。(PS.也就是每件事都要有专人负责。)

    5. 反馈收集——持续收集员工反馈,从而识别挑战和机遇:所有高层(中层管理者)每周至少安排一次与一名员工的「开始/停止/保持」谈话。在每月高管会议上分享与员工交谈时洞察到的信息。每周收集员工对机遇和挑战的反馈。中层管理团队需要对每一个机遇和挑战都负起责任且妥善处理。

    6. 了解客户——客户反馈的报告和分析要像财务数据般频繁且精准:所有高层(包括中层管理者)每周至少安排一次与终端用户的4Q谈话。( 4Q: WHO,WHY,HOW,WHAT, 他们是谁,为什么是他们,我们做得怎么样, 有什么需要改进的)在每月高管会议上分享与终端用户交谈时洞察到的信息;所有员工都参与到客户数据的采集;中层管理团队需要对每一位用户的反馈都负起责任且妥善处理。

    7. 核心价值观——在企业内部确保核心价值观和宗旨是有活力的:挖掘核心价值观,明确宗旨,让一位员工都清晰了解。所有高层和中层管理人员都应依据核心价值观和宗旨施行奖惩。人力资源流程需符合核心价值观和宗旨(招聘、入职、绩效考评、激励等流程);每季度应确定并实施行动,以强化核心价值观和宗旨。

    8. 明确战略目标——员工可以准确地表述公司战略的以下关键要素:宏伟的目标、艰难的目标和大胆的目标。(PS.「BHAG」Big,Hairy,Audacious Goals也翻译成胆大包天的目标)– 进展可追踪且可见。核心客户群 – 能够用25个以内的词描述;品牌承诺 – 每周相应品牌承诺的KPI报告;电梯演讲 – “你的公司是做什么的?” 能给出一个令人信服的回答。

    9. KPI——所有员工都可以定量地回答他们是否度过了美好的一天或一周:每周每个人汇报1到2项关键绩效指标(KPI);每个员工都有1个关键数字,与公司季度的关键数字一致(清晰的见解);每一个人/团队有3-5个季度优先事项,并与公司保持一致;所有高层和中层管理者都有一个教练(或同侪教练)来监督自己是否对行为变化付起了责任。

    10. 跟踪管理——公司的计划和业绩对所有人可见。为每周例会设立一个现实或虚拟的“情境室”。核心价值观、宗旨和优先级应自上而下传达到位。计分牌显示关键绩效指标和关键数字事件的进展。使用系统跟踪管理关联的优先级事项和关键绩效指标。

    如果你逐条阅读洛克菲勒习惯,再和自己的组织,公司的习惯做对比,能看到差距和改进的希望所在。在中国流传甚广,影响深远的《基业长青》一书的作者吉姆·柯林斯,本人就深受洛克菲勒习惯的影响。举一个例子,书中有一节,标题就叫「BHAG」Big,Hairy,Audacious Goals,翻译成「胆大包天的目标」,就是类似美国总统肯尼迪在1960年宣布的 Apollo (阿波罗)计划,用10年左右时间,要送人到月球旅行,再安全返回。

    可以这样说,现代管理学的要素都能在这10条习惯中找到影子。

    知道了洛克菲勒的十条习惯之后,如果实践也非常关键,下文简单介绍了如何实践《洛克菲勒习惯》


    ]]>
    taoCMS-基于php+sqlite最小巧的CMS 2018-12-09 15:12:26