这个没有任何毛病,对不对?
然后还需要特别注意的是,我说的是“在运行时”修改。
怎么修改?
很简单,ElasticJob 其实提供了对应的管理后台页面可以进行参数修改,但是我这里偷个懒,难得去部署对应的管理后台,,准备换个简单的思路。
因为前面说了,ElasticJob 使用的是 zk 做为自己的注册中心,我直接用工具连接上 zk,然后修改 zk 节点就行了。
我是怎么知道修改 zk 的哪个节点的呢?
别着急,等下就讲,歪师傅先带你看效果。
我这里用的工具是 ZooInspector,修改之后直接点击保存:
然后,朋友们,注意了,看日志输出
为了让你看的更加清楚,我把关键日志单独拿出来:
第一台机器上的日志是这样的:
第二台机器上的日志是这样的:
和我们前面推理的结果一模一样。
好,到这里就可以解答我的一个“按下不表”了。
首先,shardingTotalCount 叫做作业分片总数,在我前面的例子中,作业分片总数一共是 3 片:
分成三片之后,Elasticjob 怎么知道每一片应该处理哪些数据呢?
它不知道,它也不用知道。它只需要告诉每一台服务器:“来,哥们,给你一个号你拿着。你们这波一共有多少多少个人,你是第几片。”
就完事了。
因为“昨日成功的订单”这个总的要处理的数据是不变的,所有每一台服务器知道一共要把这批数据分成几片,自己是第几片后,通过代码就能拿到对应的该处理的数据。
然后你再去看官方描述中关于“分片项”你大概就能知道这到底是个啥玩意了:
有的哥们比较猛,一次拿到两个号,也没关系,就是多处理一份数据嘛。这种情况就适用于两台机器的性能不一致的情况。
但是我用这个案例并不是为了引出“性能不一致”这种极少数的情况,而是为了这个...
当我再启动一个新的服务器,当第三台服务器加入之后,我们啥也没干,它自己就开始处理任务了。
3 个分片,一台服务器处理一个分片的数据。
能自动加入,就能自动退出,所以假设我把一台服务给关闭了:
从日志可以看出来,数据并没有丢。
第一台机器把本来该在下线的这台服务器上处理的数据给接管了:
好了,到这里,基本功能就算演示完成,可以适当的响起一些掌声了。
啥原理啊?
其实关于原理,官方文档上也按照步骤进行了比较详细的说明:
如果你不了解 zk 的大致工作原理、节点特性、监听机制啥的,后面肯定会看得比较懵逼。
所以需要先去补一下这方面的信息,对于这部分的描述和源码的解读有很大帮助。
如果你能大致理解 zk 的工作原理,那么整体读下来其实没有什么特别难以理解的地方,如果要深入理解每一个步骤的话,那肯定要读一下源码的。
步骤都有了,去找对应的源码,不就是按图索骥,手拿把掐的事情吗。
在阅读源码之前,还有一个非常重要的东西要铺垫一下,前面也说了:基于 zk 做的注册中心。
所以你必须要了解“注册中心的数据结构”是怎么样的,每个节点是干啥的,才能理解代码里面操作 zk 节点的时候,到底是什么含义。
关于注册中心的数据结构,文档上也有介绍:
我觉得这个还是非常重要的,所以我多啰嗦几句,主要给你看看实际的数据是怎么样的。
还是以我本地启动三个服务为例。
启动起来之后,看 zk 上注册了这些节点:
其中“why-elastic-job”和“springJob”分别是我们写在 application.yml 里面的 ZooKeeper 的命名空间和 Job 名称:
config 节点
config 节点里面是作业配置信息,以 YAML 格式存储:
可以看到节点里面实际的值比我们配置的多,因为有很多默认项。每个默认项是干啥的,就自己去研究吧。
前面我说的“运行时修改”,就修改的是这个地方信息。
我为什么知道改这里?
还不是官网告诉我的。
instances 节点
该节点是作业运行实例信息,子节点是当前作业运行实例的主键。
作业运行实例主键由作业运行服务器的 IP 地址和 PID 构成。
作业运行实例主键均为临时节点,当作业实例上线时注册,下线时自动清理。注册中心可以监控这些节点的变化,来协调分布式作业的分片以及高可用。
具体到我们这个案例中,是这样的:
instances 下面有三个子节点,代表有三个微服务。
假设我停止运行一个服务,由于是 zk 的临时节点,这个地方就会变成 2 个:
sharding 节点
作业分片信息,子节点是分片项序号,从零开始,至分片总数减一。比如我们这里就是 0 到 2:
分片项序号的子节点存储详细信息,每个分片项下的子节点用于控制和记录分片运行状态:
可以看到 0,2 分片是运行在同一个 instance 上的,这一点和日志是匹配的:
sharding 下除了 instance 节点外,可能还有其他的节点,详细信息说明如下:
servers 节点
作业服务器信息,子节点是作业服务器的 IP 地址。
可在 IP 地址节点写入 DISABLED 表示该服务器禁用。
在新的云原生架构下,servers 节点大幅弱化,仅包含控制服务器是否可以禁用这一功能。
为了更加纯粹的实现作业核心,servers 功能未来可能删除,控制服务器是否禁用的能力应该下放至自动化部署系统。
leader 节点
作业服务器主节点信息,下面有三个子节点:
除了节点介绍外,在官网描述上有这样的一句话:
换句话说就是,如果你想了解作业,那这个节点是很重要的。看源码的时候,需要特别关注对于 leader 节点下的操作。
在我们的案例中,instance 里面的信息是这样的:
表示这个节点是主节点。
源码
知道了 zk 上每个节点的用处,看源码的时候比着看就行了。
源码比较多,歪师傅这里只能带着你做个非常简单的导读。
首先,因为很多逻辑都是基于 zk 节点在来做的,所以最重要的是各种各样的 zk 节点监听器,ElasticJob 在启动时,会执行这个方法,开启监听器:
比如前面说的这个节点:
如果这个节点存在,则说明需要重新分片,对应的监听器是这个:
那么什么时候会触发“重新分片”呢?
所以在 shardingListenerManager 监听器里面我们可以看到这两个逻辑:
满足条件之后,就会执行设置重新分片标识的代码:
该方法里面,创建了一个新的节点:
这个节点,就是它:
再比如,看看这个方法:
这个方法是做对作业进行分片逻辑的。
对作业进行分片,首先我们要知道当前有哪些实例在运行,对不对?
那怎么才能知道呢?
instances 节点请求出战:
shardingIfNecessary 方法的第一行逻辑就是读取 instances 节点下的数据:
获取到节点之后,是不是就可以分片了?
理论上是这样的,但是别着急,你看源码里面还有这样一个判断:
isLeaderUntilBlock,看方法名称也知道了,看看 Leader 节点是不是到位了,如果没到位,需要等一下 Leader 选举结束。
怎么判断 Leader 节点是不是到位了?
前面文档中说了,就是看这个节点是否存在:
对应到源码就是这样的:
所以这就是我前面说的,你看源码的时候得结合 zk 节点的用途一起看,知道节点的用途就能理解源码里面操作节点的目的是什么。
然后,在这里多说一句。
shardingIfNecessary 这个方法是读取配置,处理分片逻辑的。
但是这个方法在每一个实例中都会运行,岂不是每个实例都会执行一次分片逻辑?
这样处理的话,由于多个地方执行分片逻辑,就需要考虑冲突和一致性的问题,导致逻辑非常的复杂。
虽然这个方法每个实例都会执行,但是其实只需要有一个实例执行分片逻辑就行了。
那么哪个节点来执行呢?
你肯定也猜到了,当然是主节点来干这个事儿嘛。如果当前节点不是主节点 return 就完事了:
怎么看当前节点是否是主节点呢?
前面已经出现多次了,zk 里面记录着的:
如果当然节点是主节点,就接着往下执行,就是“作业分片策略”了:
目前官方提供了三个不同的分片策略:
对应的实现类是这样的:
逻辑都非常简单,上手 Debug 两次就能摸清楚。
建议直接把项目拉下来,然后从测试用例入手。
好了,源码导读就到这里了。
我觉得我已经算是告诉你关于 ElasticJob 源码阅读的方式和注意点,如果你掌握到了,留言区留言“清晰”二字,支持一波。
如果你还是云里雾里的,没事,是我的问题。大胆的说出来:什么玩意?看求不懂。呸,垃圾作者。
如果你是第一次接触到 ElasticJob,那么读到这里的时候,你的内心关于 ElasticJob 应该还有很多疑问以及不清楚的细节。
很好,带着你的问题,去翻源码吧。
源码之下无秘密。
下面这个环节叫做[荒腔走板],技术文章后面我偶尔会记录、分享点生活相关的事情,和技术毫无关系。我知道看起来很突兀,但是我喜欢,因为这是一个普通博主的生活气息。
荒腔走板
这周终于是把《长安三万里》看了,之前一直想看,但是又被三个小时的时长劝退。
我个人觉得确实是值得豆瓣高分的。
看完之后,包括看的过程中,我老是想起之前在网上看到的一段话,关于“一颗子弹”和“教育闭环”的。
“一颗子弹”是指在《我与地坛》看到的一段书评,其内容是:一个人十三四岁的夏天,在路上捡到一支真枪,因为年少无知,天不怕地不怕,他扣下扳机。没有人死,也没有人受伤,他认为自己开了空枪。后来他三十岁或者更老,走在路上听到背后隐隐约约的风声。他停下来回过身去,子弹正中眉心。
“教育闭环”是指教育具有长期性和滞后性,起初你只能理解表层的道理,直到多年后的某个瞬间,你才能真正领悟到书上知识的真谛,此时教育的任务才算真正完成。
我小时候读到“两岸猿声啼不住,轻舟已过万重山”的时候,重点总是在“两岸猿声”上,想象着猿猴的叫声是什么样的,那是一番怎样有趣的画面。
后来,甚至可以说是今年,这个电影上映之后,我才明白当年读书的时候我忽略的“轻舟已过万重山”背后才是有更加蜿蜒曲折、激动人心的故事。
这句诗就是当年的那一颗子弹,命中了马上三十岁的我,至此,教育才算完成了闭环。
今年,让我产生同样感受的,还有当年完全忽略的这句话:孔乙己是站着喝酒而穿长衫的唯一的人穿的虽然是长衫,可是又脏又破似平十多年没有补,也没有洗。他对人说话,总是满口之乎者也叫人半懂不懂的。
此外,电影中多次提到“长安”,虽然我们学的是同样的课本,读的是一样的诗,但是每个人对与“长安”的认知和理解是不一样的。
现在提到长安,我脑海中出现的第一个画面永远是当年看《河西走廊》纪录片的时候那一个画面。
第一集《使者》,张骞出使西域,被匈奴囚禁九年后同随从堂邑父出逃,继续西行。
靠强大意志力穿越塔克拉玛干沙漠和帕米尔高原,到达西域。回程再次被俘,数年后带匈奴妻子和堂邑父又一次出逃东归。
十三年后,终于再次望到长安城,张骞匍匐在地,长跪不起。
西北望长安,可怜无数山。
这一跪,看的我眼泪婆娑。