怎么用eclipse做网站开发,wordpress分类页置顶信息,wordpress 返回顶部插件,网站关键词之间用什么符号隔开源宝导读#xff1a;MIP集成平台是为了解决企业大量异构系统之间快速、稳定集成的需要#xff0c;助力企业数字化转型#xff0c;明源云自主研发的平台系统。本文将对事件任务分派场景的架构设计以及实践成果进行分享。背景MIP集成平台是为了解决企业大量异构系… 源宝导读MIP集成平台是为了解决企业大量异构系统之间快速、稳定集成的需要助力企业数字化转型明源云自主研发的平台系统。本文将对事件任务分派场景的架构设计以及实践成果进行分享。背景 MIP集成平台是为了解决企业大量异构系统之间快速、稳定集成的需要助力企业数字化转型明源云自主研发的平台系统。在MIP中事件中心组件提供了低耦合、准实时、高可靠的数据或消息传输服务解决企业信息系统之间的异步的通知和数据同步需求。在事件管理中用户可以通过创建事件源和事件订阅者来实现事件的订阅与发布最终实现数据或消息在应用之间进行传递。后台系统会通过调度模块进行事件任务的分配然后下发到运行模块进行事件任务的运行监听和订阅本文将对事件任务分派场景的架构设计以及实践成果进行分享。基于篇幅本次主要分享分派调度策略的处理逻辑的这个层面。一、需求分析 基于上面的描述我们可以认为这是一个分布式任务调度的场景相对简单且有其特点。调度分配以事件为单位调度时只需要根据分配原则把指定的事件在运行模块节点上启动即可。持续运行不需要Job形式的定时调度为了保证准实时性事件任务一旦启动将会持续运行除非重新被分配。一致性为了保证消息和数据不会重复同一时间一个事件只能在一个运行节点中执行。故障转移当一个运行节点不可用时需要把上面正在运行的事件任务转移到其它的运行节点中运行。动态平衡当有新的运行节点加入时需要转移部分事件任务到新的节点以保证各节点的任务数平衡同时当有事件被新发布或下线时也要执行平衡。.net core技术栈和Consul中间件MIP采用.net core进行开发同时引入了Consul来支持集群一致性所以尽量在已有条件基础上考虑解决方案。二、架构设计 通过上面的分析和权衡考虑我们没有选择现成的第三方调度框架而是进行自主研发而集群一致性方面则依赖于Consul作为基础。 所有的调度结果保存成一份清单数据存储在Consul中然后再根据清单数据下发事件任务的启动/停止命令清单数据的结构类似于这样我们把主要功能分为调度模块和运行模块两个部分参考图1。2.1 调度模块 调度模块主要负责事件任务的分配逻辑并发送相应的事件任务启动/停止命令到运行模块。事件任务调度调度模块从Consul中获取正在运行的运行模块服务信息把事件任务平均分配到运行模块节点中。一致性因为调度逻辑占用资源较小所以不需要所有的节点都执行逻辑各节点通过争抢Consul的KV锁来完成Leader的选举由Leader来执行调度逻辑。根据运行模块各节点的状态动态的调整分配超过一定时间持续无法连接的节点认为是故障节点。事件任务调度的清单数据存储到Consul中。接收从事件管理发送过来的事件发布、下线通知重新调度。事件任务调度的三个触发点第一次启动初始化事件变化通知定时触发。2.2 运行模块 运行模块则接收调度模块的命令负责执行事件任务并把启动/停止的状态结果返回给调度模块并提供查询事件任务状态的API。事件任务运行接收调度命令启动/停止事件任务的运行并且保证在接收并完成事件任务的启动命令后事件持续运行即如果事件任务异常退出则重新启动。一致性由调度模块来保证根据调度模块的命令来执行任务。提供当前正在运行的事件任务的状态查询API。把自身服务注册到Consul反映节点的健康状态。当发现自身不健康时无法连接到Consul超过一定时间后需要小于调度模块认为运行节点故障的间隔时间停止当前节点上的所有事件任务运行。图1 架构示意图三、调度场景分析3.1 第一次启动初始化 第一次启动时事件任务清单数据为空所以全新获取所有的事件信息和所有的运行节点信息按照平均分配的逻辑分配事件任务先把分配结果保存到清单再根据清单逐个去调用运行节点启动事件任务。图2 第一次启动初始化3.2 运行节点新增 当运行节点新增时根据已经运行的事件任务清单还是采取平均分配的原则从正在运行的节点上移出部分事件任务到新节点上启动。图3 运行节点新增3.3 运行节点故障/下线 当判断出某个节点的状态为不可用时把该节点上所有的任务转移到其它节点上执行。图4 运行节点故障/下线3.4 事件发布/下线 当调度模块接收到事件的发布/下线通知时重新执行调度逻辑去相应的启动或停止事件任务。图5 事件发布/下线四、实现逻辑 通过前面的分析接下来就是考虑如何去实现了。我们分析了几种调度发生的场景是不是按照这个逻辑把代码实现出来就可以了呢其实不然细想一下我们会发现还有一些其它特性需要考虑主要从扩展性、可靠性和性能方面考虑。我们发现每一种调度场景下做的事情都很类似比如都需要重新获取运行模块节点信息和任务清单并去最终都是去调用运行模块节点的api去执行操作那么我们是不是需要在实现设计时再往上抽象一层如果再抽象是否只是把通用逻辑提取出来在不同的调度场景调用呢我们现在的处理思路是根据分配逻辑生成任务清单再根据清单去调用运行模块的api执行任务的启动/停止但是如果在两次调度的间隔内某一个运行模块节点上的某一个或某几个任务异常停止了比如某个运行节点执行了重启但是因为我们是定时调度没有检测到节点的一次下线和一次上线动作我们如何保证最终一定是按照清单在运行任务还是运行节点重启了我们检测到了下线和上线但是因为节点下线超过一定时间我们才认为是真正的下线了并且马上又有一次新节点的上线那这个逻辑是不是又变的复杂了我们的程序到底应该如何处理呢重启运行节点是不是需要单独列为一个场景呢上面我们单独分析了每个调度的场景逻辑看上去也还简单但是如果是多个场景同时发生我们又该如何实现逻辑呢相互之间是否会有冲突又如何保证可靠性呢目前每一个事件的发布/下线都会发送一次通知如果在批量操作时会频繁触发调度有没有办法在不改变事件通知的情况下尽量合并调度呢 我们回过头来仔细想一想其实从计算机的角度看我们的程序主要做了两件事情根据当前的情况计算出任务分配清单生成事件任务操作命令。根据生成好的命令调用运行节点api。 接下来就比较清晰了我们的程序就是要保证上面两件事件稳定、可靠、高效的完成大体的处理逻辑如下图6 实现逻辑 接下来我们再把两种特殊场景接入到这种日常调度逻辑里面来第一次初始化时在最开始的时候根据节点和总的事件清单生成一个完整的节点任务清单然后直接进入日常调度逻辑。当有新的事件发布/下线通知进来的时候根据通知内容去更新节点任务清单同时对内存变量进行一个标记然后直接进入日常调度逻辑。并且目前调度的定时器是2秒触发一次但是不会每次都执行调度逻辑而是会判断是否达到定时调度的时间或者是事件变更通知的内存标记为已变更也避免频繁调度造成的性能和稳定性风险。五、结束 经过我们的分析设计我们把一个看似繁杂的分布式调度的场景变的简单了提炼出其中的核心逻辑然后去实现和完善它以不变应万变只要保证其中的核心逻辑的稳定不管外面的接入场景如何多变我们都能从容的应对。 在本篇中我们没有去涉及什么很高深的框架和组件以及具体的实现代码主要还是对我们在实现这个分布式调度过程中的思路进行了一些分享。我们不敢说一定是最对最好的但是当思路清楚了实现起来也就不复杂了。------ END ------作者简介王同学 架构师目前负责ERP集成平台架构的规划与设计工作。也许您还想看MIP服务发现的高可用架构实践基于消息的高稳定集成架构方案一个全栈式的应用集成平台打破“信息孤岛”研发协同平台持续集成2.0架构演进