1.本发明涉及互联网
技术领域:
:,具体地,涉及分布式可观察的任务调度系统及方法。
背景技术:
::2.服务号管理系统在和微信服务号后台进行交互时,涉及到文字、图片等素材的上传。首先,需要比对数据库和微信服务号后台的素材的差异性。然后,将数据库内的新增和删除的记录,同步到微信服务号后台。3.多个服务号,每个服务号每次上千甚至上万的素材同步数量,会极大地占用单台机器的计算资源。4.专利文献cn102387208b(申请号:201110324762.3)公开了一种分布式任务调度方法,包括如下步骤:任务表分发器向多个任务机发送任务表;多个任务机分别根据任务表中的对应的任务及依赖关系表确定自身是否为起始任务机;起始任务机根据任务表执行起始任务机所对应的任务;在对应的任务执行完成后,起始任务机根据依赖关系表通知起始任务机的后继任务机执行相应的任务。5.为了解决现有技术中存在的不足,同时提出了以下初始方案:6.通过redis队列来缓冲多个服务号在同一时间内的素材同步操作;但上述方案,仍存在一个问题,那就是队列排队问题。在后面执行的任务,必须等待前面的任务结束后,才能够被执行。在实际生产环境中,这个时间是1到2个小时,严重影响了业务人员的工作效率。为了解决上述问题,又提出了分布式可观察的任务调度系统。技术实现要素:7.针对现有技术中的缺陷,本发明的目的是提供一种分布式可观察的任务调度方法及系统。8.根据本发明提供的一种分布式可观察的任务调度方法,包括:9.步骤s1:当服务号管理系统发布任务时,从redis缓存中获取当前任务的序列号;10.步骤s2:服务号管理系统通过消息队列将任务分发至专门的任务执行单元;11.步骤s3:任务执行单元将任务进度写入redis中;12.步骤s4:通过redis中保存的序列号信息,记录序号总数,通过当前执行的序号计算队列排队进度。13.优选地,所述消息队列是通过rabbitmq实现的,通过负载均衡算法进行任务调度,包括:任务分发、任务进度查询、任务排队查询、任务监听、异常处理以及消息确认。14.优选地,所述任务执行单元以集群形式部署,并根据服务号素材同步的数据量动态进行扩容或升配。15.优选地,利用分布式锁和redis原子计数,基于单线程执行特点,获取全局唯一序列号。16.优选地,任务执行单元通过cms乐观锁,利用单个守护线程上报每个任务进度;当任务进度无更新时,当前线程进入阻塞等待,则降低cpu占用。17.优选地,将任务信息存储于threadlocal内,并与当前执行线程所绑定。18.优选地,将任务进度利用异步线程提交进度机制写入redis中。19.根据本发明提供的一种分布式可观察的任务调度系统,包括:20.模块m1:当服务号管理系统发布任务时,从redis缓存中获取当前任务的序列号;21.模块m2:服务号管理系统通过消息队列将任务分发至专门的任务执行单元;22.模块m3:任务执行单元将任务进度写入redis中;23.模块m4:通过redis中保存的序列号信息,记录序号总数,通过当前执行的序号计算队列排队进度。24.优选地,所述消息队列是通过rabbitmq实现的,通过负载均衡算法进行任务调度,包括:任务分发、任务进度查询、任务排队查询、任务监听、异常处理以及消息确认;25.所述任务执行单元以集群形式部署,并根据服务号素材同步的数据量动态进行扩容或升配。26.优选地,利用分布式锁和redis原子计数,基于单线程执行特点,获取全局唯一序列号;27.任务执行单元通过cms乐观锁,利用单个守护线程上报每个任务进度;当任务进度无更新时,当前线程进入阻塞等待,则降低cpu占用;28.将任务信息存储于threadlocal内,并与当前执行线程所绑定;29.将任务进度利用异步线程提交进度机制写入redis中。30.与现有技术相比,本发明具有如下的有益效果:31.1、本发明通过采用分布式可观察的任务调度系统,解决了分布式环境下,单个应用实例执行任务的性能瓶颈,并提供了强大的可观察性,实时反馈任务调度过程中的状态;32.2、本发明可以应用于多种业务场景,例如各种类型的数据同步,数据处理,或者是具体的业务场景类似医院排队,点餐等候等;33.3、本发明通过分布式调度,实现了批量处理任务的效果;可根据应用场景,动态进行扩容,不再受限于单体应用的性能瓶颈;34.4、本发明通过进度上报,实现了任务进度和状态可查询的效果,在满足任务高效稳定执行条件下,同时提供了具有通用性的可观察性。附图说明35.通过阅读参照以下附图对非限制性实施例所作的详细描述,本发明的其它特征、目的和优点将会变得更明显:36.图1为初始方案示意图。37.图2为分布式可观察的任务调度系统示意图。38.图3为分布式可观察的任务调度系统示意图。39.图4为异步线程提交进度的机制示意图。40.图5为代码实现示意图。41.图6为redis数据结构图。具体实施方式42.下面结合具体实施例对本发明进行详细说明。以下实施例将有助于本领域的技术人员进一步理解本发明,但不以任何形式限制本发明。应当指出的是,对本领域的普通技术人员来说,在不脱离本发明构思的前提下,还可以做出若干变化和改进。这些都属于本发明的保护范围。43.实施例144.根据本发明提供的一种分布式可观察的任务调度方法,如图1至6所示,包括:45.步骤s1:当服务号管理系统发布任务时,从redis缓存中获取当前任务的序列号;46.步骤s2:服务号管理系统通过消息队列将任务分发至专门的任务执行单元;47.步骤s3:任务执行单元将任务进度写入redis中;48.步骤s4:通过redis中保存的序列号信息,记录序号总数,通过当前执行的序号计算队列排队进度。49.具体地,所述任务队列是通过rabbitmq实现的,通过负载均衡算法进行任务调度,包括:任务分发、任务进度查询、任务排队查询、任务监听、异常处理以及消息确认。50.具体地,所述任务执行单元以集群形式部署,并根据服务号素材同步的数据量动态进行扩容或升配。51.具体地,任务执行单元将任务进度写入redis中,利用分布式锁和redis原子计数,基于单线程执行特点,获取全局唯一序列号,基于全局唯一序列号计算排队进度。如图3所示,任务进度包括进度、状态和序号;每个执行线程在上报自己的任务进度时,任务进度大于0时,则说明该任务正在处理中,则状态为running;排队进度=取正值(任务的序号-当前正在执行的序号);52.具体地,任务执行单元通过cms乐观锁,利用单个守护线程上报每个任务进度;当任务进度无更新时,当前线程进入阻塞等待,则降低cpu占用。具体地,每100ms,扫描一次所有的任务进度,只有任务进度有更新的,会同步更新到redis上。如果每个任务都没有更新,则阻塞并等待任务更新进度。53.具体地,将任务信息存储于threadlocal内,并与当前执行线程所绑定。54.具体地,将任务进度利用异步线程提交进度机制写入redis中。55.更为具体地,从redis缓存上,获取序号;将具体任务推送到消息队列中,直至被消息队列监听器进行消费;在任务在被正式消费之前,更新redis的正在运行计数;任务被真正的执行,并实时更新任务上下文,更新任务的进度。有任务进度监听器,每隔100ms上报任务的进度;任务结束后,更新redis上的任务的状态为已结束状态。56.根据本发明提供的一种分布式可观察的任务调度系统,包括:57.步骤s1:当服务号管理系统发布任务时,从redis缓存中获取当前任务的序列号;58.步骤s2:服务号管理系统通过消息队列将任务分发至专门的任务执行单元;59.步骤s3:任务执行单元将任务进度写入redis中;60.步骤s4:通过redis中保存的序列号信息,记录序号总数,通过当前执行的序号计算队列排队进度。61.具体地,所述任务队列是通过rabbitmq实现的,通过负载均衡算法进行任务调度,包括:任务分发、任务进度查询、任务排队查询、任务监听、异常处理以及消息确认。62.具体地,所述任务执行单元以集群形式部署,并根据服务号素材同步的数据量动态进行扩容或升配。63.具体地,任务执行单元将任务进度写入redis中,利用分布式锁和redis原子计数,基于单线程执行特点,获取全局唯一序列号,基于全局唯一序列号计算排队进度。如图3所示,任务进度包括进度、状态和序号;每个执行线程在上报自己的任务进度时,任务进度大于0时,则说明该任务正在处理中,则状态为running;排队进度=取正值(任务的序号-当前正在执行的序号);64.具体地,任务执行单元通过cms乐观锁,利用单个守护线程上报每个任务进度;当任务进度无更新时,当前线程进入阻塞等待,则降低cpu占用。具体地,每100ms,扫描一次所有的任务进度,只有任务进度有更新的,会同步更新到redis上。如果每个任务都没有更新,则阻塞并等待任务更新进度。65.具体地,将任务信息存储于threadlocal内,并与当前执行线程所绑定。66.具体地,将任务进度利用异步线程提交进度机制写入redis中。67.更为具体地,从redis缓存上,获取序号;将具体任务推送到消息队列中,直至被消息队列监听器进行消费;在任务在被正式消费之前,更新redis的正在运行计数;任务被真正的执行,并实时更新任务上下文,更新任务的进度。有任务进度监听器,每隔100ms上报任务的进度;任务结束后,更新redis上的任务的状态为已结束状态。68.实施例269.实施例2是实施例1的优选例70.本发明提供的一种分布式可观察的任务调度系统,包括:在分布式环境下,通过负载均衡算法,进行任务调度。可实时查询任务调度状态,进度,以及整体排队情况。71.分布式任务调度系统包括:72.任务序列号申请服务:利用分布式锁和redis原子计数,单线程执行特点,获取全局唯一序列号,用以计算排队进度。73.消息队列任务分发:提供rabbitmq消息分发服务层,提供任务分发,任务进度查询,任务排队查询等服务。74.消息队列任务监听:提供rabbitmq消息监听服务层,提供任务监听,异常处理,消息确认等服务。75.任务进度实时上报:通过cms乐观锁,利用单个守护线程,无阻塞实时上报每个任务进度。当任务进度无更新时,该线程会进入阻塞等待,降低cpu占用。76.对上述分布式任务调度系统进行进一步说明:77.(1)计算转移78.服务号管理系统,是单点部署的,如果作为实际的任务执行单元,会出现卡顿现象,影响用户其他的操作。故通过消息队列,将任务分发到专门的任务执行单元。消息队列并没有限定,目前通过rabbitmq实现。rabbitmq有交换机exchange的概念,在负载均衡方面,相对于kafka等以topic为主的消息队列,更加灵活。而此业务场景,系统性能的瓶颈不在消息队列,故rabbitmq适用。79.将任务执行单元以集群形式部署,可以根据服务号素材同步的数据量,动态进行扩容或者升配。80.(2)进度上报81.市面上存在的分布式任务调度系统(例如xxl-job),大部分提供了核心的任务调度功能,能够在界面上,获取到任务执行的执行结果,异常情况,执行时间等,但尚无法实时获取到任务执行的进度。82.服务号管理系统素材上传功能,需要知道任务的实时进度(时间精确到100ms级别),故上述开源的调度系统尚不能满足。83.为了满足上述需求,需要解决如下几个问题:84.任务进度需要被持久化,并能够被查询。85.提供接口给业务开发者,上报任务执行的进度。86.业务逻辑本身的执行,不能受到上报动作的影响。87.为了解决第一个问题,引入了redis。redis是基于内存的,读写性能都非常好,故相对于传统数据库,更加适用于当前场景。任务进度,需要写入redis。88.格式如下:[0089][0090][0091]为了解决第二个问题,提供如下接口。[0092]tasktask=taskcontext.gettask();[0093]task.setprogress(100);[0094]taskcontext.commit(tasktask);[0095]为了降低和业务代码的耦合度,任务信息task,存在于threadlocal内,与当前执行线程所绑定。[0096]为了解决第三个问题,提出了异步线程提交进度的机制。[0097]在任务执行单元内,执行任务的线程数是提前设定好的,像上传这种网络交互较多的场景,一般设置核心线程数为cpu核数的两倍左右。假设核数为4,则线程数为8。[0098]slot是一个长度为8的数组,数组中存放类型为task的实例的引用。初始化时,每个线程根据自己的线程工厂分配的线程名称中的序号,绑定了slot内对应的索引位置。[0099]在执行线程获取任务实例,并提交进度信息后,实际上,是对slot内,对应索引位置的任务进行修改。因为每个执行线程,都有自己对应的索引位置,故不会产生任何冲突,也不需要进行阻塞。[0100]由上报线程每隔100ms,扫描slot数组内的任务信息,进行上报。每个任务实例中,会保存最后一次更新时间和最后一次上报时间,如果更新时间大于等于上报时间的话,则说明该任务的信息,需要被刷新到redis。该机制确保了,那些进度没有更新的任务,不会被反复地写入到redis。[0101]上报过程中,选择单个上报线程去处理,可以将执行线程从上报这个流程中解放出来,执行线程不会因为和redis交互而被网络io而阻塞。并且,执行线程上报的频率非常快,如果每一次的更新,都需要同步到redis,那么交互频率过高,redis压力也会陡升。通过上报线程专门处理任务信息,可以在空闲时阻塞,来降低cpu占用,并能够通过100ms的时间间隔来控制和redis交互的频率。[0102](3)队列排队[0103]在能够获取每个任务的同时,还需要知道任务在rabbitmq中的排队情况。通过在redis上保存序列号信息,来记录序号总数,和当前执行的序号,来“粗略”地计算队列排队情况。[0104]jds:wechat:currentcount[0105]jds:wechat:registeredtable[0106]jds:wechat:runningcount[0107]其中,currentcount是序列号计数器。[0108]runningcount是当前序列号。[0109]每当服务号管理系统发布任务时,从redis获取序列号计数器的计数,作为该任务的序列号。[0110]每当任务执行单元执行任务时,会将任务的进度和该任务的序列号更新到runningcount中。但条件是,该任务的序列号必须比redis上的runningcount大。[0111]查询任务排队情况时,通过registeredtable获取到对应上报的task信息,并通过task的序列号和runningcount的差值,来判断task是否已经被执行,或者前面还有多少任务执行后,才能够被执行。[0112]本领域技术人员知道,除了以纯计算机可读程序代码方式实现本发明提供的系统、装置及其各个模块以外,完全可以通过将方法步骤进行逻辑编程来使得本发明提供的系统、装置及其各个模块以逻辑门、开关、专用集成电路、可编程逻辑控制器以及嵌入式微控制器等的形式来实现相同程序。所以,本发明提供的系统、装置及其各个模块可以被认为是一种硬件部件,而对其内包括的用于实现各种程序的模块也可以视为硬件部件内的结构;也可以将用于实现各种功能的模块视为既可以是实现方法的软件程序又可以是硬件部件内的结构。[0113]以上对本发明的具体实施例进行了描述。需要理解的是,本发明并不局限于上述特定实施方式,本领域技术人员可以在权利要求的范围内做出各种变化或修改,这并不影响本发明的实质内容。在不冲突的情况下,本技术的实施例和实施例中的特征可以任意相互组合。当前第1页12当前第1页12