集成平台集群任务动态分派

源宝导读:MIP集成平台是为了解决企业大量异构系统之间快速、稳定集成的需要,助力企业数字化转型,明源云自主研发的平台系统。本文将对"事件任务分派"场景的架构设计以及实践成果进行分享。

背景

    MIP集成平台是为了解决企业大量异构系统之间快速、稳定集成的需要,助力企业数字化转型,明源云自主研发的平台系统。在MIP中,事件中心组件提供了低耦合、准实时、高可靠的数据或消息传输服务,解决企业信息系统之间的异步的通知和数据同步需求。在事件管理中,用户可以通过创建事件源和事件订阅者,来实现事件的订阅与发布,最终实现数据或消息在应用之间进行传递。后台系统会通过调度模块进行事件任务的分配,然后下发到运行模块进行事件任务的运行(监听和订阅),本文将对"事件任务分派"场景的架构设计以及实践成果进行分享。基于篇幅,本次主要分享分派调度策略的处理逻辑的这个层面。

一、需求分析

    基于上面的描述,我们可以认为这是一个分布式任务调度的场景,相对简单且有其特点。

  1. 调度分配以事件为单位,调度时只需要根据分配原则把指定的事件在运行模块节点上启动即可。

  2. 持续运行,不需要Job形式的定时调度,为了保证准实时性,事件任务一旦启动,将会持续运行,除非重新被分配。

  3. 一致性,为了保证消息和数据不会重复,同一时间一个事件只能在一个运行节点中执行。

  4. 故障转移,当一个运行节点不可用时,需要把上面正在运行的事件任务转移到其它的运行节点中运行。

  5. 动态平衡,当有新的运行节点加入时,需要转移部分事件任务到新的节点,以保证各节点的任务数平衡;同时当有事件被新发布或下线时,也要执行平衡。

  6. .net core技术栈和Consul中间件,MIP采用.net core进行开发,同时引入了Consul来支持集群一致性,所以尽量在已有条件基础上考虑解决方案。

二、架构设计

    通过上面的分析和权衡考虑,我们没有选择现成的第三方调度框架,而是进行自主研发,而集群一致性方面则依赖于Consul作为基础。
    所有的调度结果保存成一份清单数据,存储在Consul中,然后再根据清单数据下发事件任务的启动/停止命令,清单数据的结构类似于这样:


我们把主要功能分为"调度模块"和"运行模块"两个部分,参考图1。

2.1 调度模块:

    调度模块主要负责事件任务的分配逻辑,并发送相应的事件任务启动/停止命令到运行模块。

  1. 事件任务调度,调度模块从Consul中获取正在运行的运行模块服务信息,把事件任务平均分配到运行模块节点中。

  2. 一致性,因为调度逻辑占用资源较小,所以不需要所有的节点都执行逻辑,各节点通过争抢Consul的KV锁来完成Leader的选举,由Leader来执行调度逻辑。

  3. 根据运行模块各节点的状态,动态的调整分配(超过一定时间持续无法连接的节点认为是故障节点)。

  4. 事件任务调度的清单数据存储到Consul中。

  5. 接收从"事件管理"发送过来的事件发布、下线通知,重新调度。

  6. 事件任务调度的三个触发点:第一次启动初始化,事件变化通知,定时触发。


2.2 运行模块:

    运行模块则接收调度模块的命令,负责执行事件任务,并把启动/停止的状态结果返回给调度模块,并提供查询事件任务状态的API。

  1. 事件任务运行,接收调度命令,启动/停止事件任务的运行,并且保证在接收并完成事件任务的启动命令后事件持续运行(即如果事件任务异常退出则重新启动)。

  2. 一致性,由调度模块来保证,根据调度模块的命令来执行任务。

  3. 提供当前正在运行的事件任务的状态查询API。

  4. 把自身服务注册到Consul,反映节点的健康状态。

  5. 当发现自身不健康时(无法连接到Consul),超过一定时间后(需要小于调度模块认为运行节点故障的间隔时间),停止当前节点上的所有事件任务运行。


图1 架构示意图


三、调度场景分析

3.1 第一次启动初始化:

    第一次启动时,事件任务清单数据为空,所以全新获取所有的事件信息和所有的运行节点信息,按照平均分配的逻辑分配事件任务,先把分配结果保存到清单,再根据清单逐个去调用运行节点启动事件任务。


图2 第一次启动初始化

3.2 运行节点新增:

    当运行节点新增时,根据已经运行的事件任务清单,还是采取平均分配的原则,从正在运行的节点上,移出部分事件任务到新节点上启动。


图3 运行节点新增

3.3 运行节点故障/下线:

    当判断出某个节点的状态为不可用时,把该节点上所有的任务转移到其它节点上执行。


图4 运行节点故障/下线

3.4 事件发布/下线:

    当调度模块接收到事件的发布/下线通知时,重新执行调度逻辑,去相应的启动或停止事件任务。


图5 事件发布/下线


四、实现逻辑

    通过前面的分析,接下来就是考虑如何去实现了。我们分析了几种调度发生的场景,是不是按照这个逻辑把代码实现出来就可以了呢?其实不然,细想一下,我们会发现还有一些其它特性需要考虑,主要从扩展性、可靠性和性能方面考虑。

  1. 我们发现每一种调度场景下做的事情都很类似,比如都需要重新获取运行模块节点信息和任务清单,并去最终都是去调用运行模块节点的api去执行操作,那么我们是不是需要在实现设计时再往上抽象一层?如果再抽象是否只是把通用逻辑提取出来,在不同的调度场景调用呢?

  2. 我们现在的处理思路是,根据分配逻辑生成任务清单,再根据清单去调用运行模块的api执行任务的启动/停止,但是如果在两次调度的间隔内,某一个运行模块节点上的某一个或某几个任务异常停止了(比如某个运行节点执行了重启,但是因为我们是定时调度,没有检测到节点的一次下线和一次上线动作),我们如何保证最终一定是按照清单在运行任务?

  3. 还是运行节点重启了,我们检测到了下线和上线,但是因为节点下线超过一定时间我们才认为是真正的下线了,并且马上又有一次新节点的上线,那这个逻辑是不是又变的复杂了,我们的程序到底应该如何处理呢?重启运行节点是不是需要单独列为一个场景呢?

  4. 上面我们单独分析了每个调度的场景,逻辑看上去也还简单,但是如果是多个场景同时发生,我们又该如何实现逻辑呢?相互之间是否会有冲突,又如何保证可靠性呢?

  5. 目前每一个事件的发布/下线都会发送一次通知,如果在批量操作时,会频繁触发调度,有没有办法在不改变事件通知的情况下,尽量合并调度呢?

    我们回过头来仔细想一想,其实从计算机的角度看,我们的程序主要做了两件事情:

  1. 根据当前的情况,计算出任务分配清单,生成事件任务操作命令。

  2. 根据生成好的命令,调用运行节点api。

    接下来就比较清晰了,我们的程序就是要保证上面两件事件稳定、可靠、高效的完成,大体的处理逻辑如下:


图6 实现逻辑

    接下来我们再把两种特殊场景接入到这种日常调度逻辑里面来:

  1. 第一次初始化时,在最开始的时候根据节点和总的事件清单,生成一个完整的节点任务清单,然后直接进入日常调度逻辑。

  2. 当有新的事件发布/下线通知进来的时候,根据通知内容去更新节点任务清单,同时对内存变量进行一个标记,然后直接进入日常调度逻辑。并且目前调度的定时器是2秒触发一次,但是不会每次都执行调度逻辑,而是会判断是否达到定时调度的时间,或者是事件变更通知的内存标记为已变更,也避免频繁调度造成的性能和稳定性风险。

五、结束
    经过我们的分析设计,我们把一个看似繁杂的分布式调度的场景变的简单了,提炼出其中的核心逻辑,然后去实现和完善它,以不变应万变,只要保证其中的核心逻辑的稳定,不管外面的接入场景如何多变,我们都能从容的应对。
    在本篇中,我们没有去涉及什么很高深的框架和组件以及具体的实现代码,主要还是对我们在实现这个分布式调度过程中的思路进行了一些分享。我们不敢说一定是最对最好的,但是当思路清楚了,实现起来也就不复杂了。

------ END ------

作者简介

王同学: 架构师,目前负责ERP集成平台架构的规划与设计工作。

也许您还想看

MIP服务发现的高可用架构实践

基于消息的高稳定集成架构方案

一个全栈式的应用集成平台,打破“信息孤岛”

研发协同平台持续集成2.0架构演进

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dotcpp1115 DNA-打印图案

题目描述 小强从小就喜欢生命科学,他总是好奇花草鸟兽从哪里来的。终于, 小强上中学了,接触到了神圣的名词–DNA.它有一个双螺旋的结构。这让一根筋的小强抓破头皮,“要是能画出来就好了” 小强喊道。现在就请你帮助他吧 输入 输…

akb48_AKB48里历史——六年的终结

注:这是2012年发行的一本在BUBUKA连载的基础上补充了一些内容的粉丝公式教科书,从里面找了部分内容翻译了一下,节选的内容主要说的是2011年的事情,以当时作者的视角,是AKB48第一次新老粉丝换代的时期。前田敦子和大岛优…

[头脑风暴] 解读Docker Bridge网络模型

背景这几天在研究Kubernetes, 遇到一个有意思的nodejs镜像:luksa/kubia# 不带端口映射启动容器 docker run -it -d luksa/kubia # 连接到默认的Bridge网桥,容器IP是 172.17.0.2之后,在宿主机使用容器IP和8080 端口可访问该容器…

kodi pvr 不能安装_「家庭影音串流」电视最强播放器KODI使用方法

本文作者:空翻的帕兹文章适用电脑手机等全平台设备,在用户没有nas的情况下如何使用串流电视最强播放器KODIKodi是由XBMC基金會開發的開源媒體播放器,原名XBMC(最後一個以XBMC命名的版本是13.2「Gotham」,14.0 「Helix」是第一個以…

docker部署flask项目

项目本地运行 1.到github或者自己创建一个flask项目,确保在本地是可以运行成功的 2.上传到自己的代码仓库 服务器部署 1.安装docker yum install docker -y2.配置加速器 DaoCloud加速器采用自主研发的智能路由及缓存技术,并引入了现金的协议层优化…

.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记...

24 | 文件提供程序:让你可以将文件放在任何地方文件提供程序核心类型:1、IFileProvider2、IFileInfo3、IDirectoryContentsIFileProvider 是访问各种各样文件提供程序的接口通过这样子抽象的定义,让我们与具体的抽象文件的读取的代码进行了隔…

连接mysql数据库_解决Navicat连接MySQL数据库报错问题

今天在用Navicat连接另外一台主机上的MySQL时报错:Host is not allowed to connect to this MySQL server默认安装的mysql无法远程连接是因为MySQL默认配置了不支持远程连接引起的。解决方法:一、本地主机上登录root用户找到mysql.exe所在路径&#xff0…

洛谷T172098 子串-substr

代码如下&#xff1a; #include <iostream> #include <cstring> using namespace std;int main() {int cnt;cin >> cnt;string a, b;while (cnt--) {int n, m;cin >> n >> m;cin >> a;cin >> b;int ans 0 ;for (int i 0; i < …

在Ocelot中使用自定义的中间件(二)

在上文中《在Ocelot中使用自定义的中间件&#xff08;一&#xff09;》&#xff0c;我介绍了如何在Ocelot中使用自定义的中间件来修改下游服务的response body。今天&#xff0c;我们再扩展一下设计&#xff0c;让我们自己设计的中间件变得更为通用&#xff0c;使其能够应用在不…

机器学习理论引导 电子版_机器学习理论篇1:机器学习的数学基础(2)

本节主要就是讲述的机器学习的数学基础&#xff0c;提到数学基础&#xff0c;可能一眼就会是满眼的枯燥、没意思&#xff0c;但是成就英雄的路上注定了孤独&#xff0c;要想要真正的在学术上有所突破就必须挨得住寂寞&#xff0c;受得住孤独&#xff0c;才能真正的走进熟悉直到…

洛谷T172100 商店-贪心

解题思路&#xff1a; 贪心 代码如下&#xff1a; #include <iostream> #include <algorithm> using namespace std; const int N 100010; int a[N], w[N]; int ans;int main() {int n, m;cin >> n >> m;for (int i 1; i < n; i)cin >> a…

终结“永恒之蓝”后,再战“永恒之黑”

引子&#xff1a;2003年的“抗击非典”&#xff0c;17年后的2020年“抗击新冠”。2017年的“永恒之蓝”&#xff0c;3年后的2020年“永恒之黑”。历史&#xff1a;2017年5月13日&#xff0c;在“胖哥技术堂”中发布了《截杀“WannaCrypt”&#xff0c;终结“永恒之蓝”》。三年…

使用.Net Core编写命令行工具(CLI)

使用.Net Core编写命令行工具(CLI)命令行工具(CLI)命令行工具(CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面&#xff0c;它通常不支持鼠标&#xff0c;用户通过键盘输入指令&#xff0c;计算机接收到指令后&#xff0c;予以执行。通常认为&#xff0c;命令行工具(C…

与php有区别_php://output和php://stdout的区别

php中文网最新课程每日17点准时技术干货分享PHP包含了以php://开头的一系列输出输出流&#xff0c;如php://stdin, php://stdout等。今天查看代码时&#xff0c;忽然想到一个问题&#xff1a;php://output和php://stdout有什么区别&#xff1f;从PHP的官方文献中找答案&#xf…

浅谈 Kubernetes Scheduling-Framework 插件的实现

最近几个月一直在研究 kubernetes 的 scheduling-framework 调度框架&#xff0c;发现还是十分有意思的&#xff0c;我自己也实现了一个基于 scheduling-framework 调度框架的自定义调度器&#xff0c;希望感兴趣的同学一起学习&#xff1a;https://github.com/NJUPT-ISL/Yoda-…

C++实现线段树(lazy-tag方法)-区间修改,区间查询

代码如下&#xff1a; #include <iostream> using namespace std; const int N 10010; typedef long long LL; LL input[N];struct node {int l, r;LL sum;LL add; } tree[4 * N];void build(int l, int r, int u) {tree[u].l l;tree[u].r r;if (l r) {tree[u].sum …

.NET Core开发实战(第25课:路由与终结点:如何规划好你的Web API)--学习笔记(上)...

25 | 路由与终结点&#xff1a;如何规划好你的Web API路由系统在 ASP.NET MVC 框架里面就已经存在了&#xff0c;在 ASP.NET Core 框架里面进行了改进路由系统的核心作用是指 URL 和 应用程序 Controller 的对应关系的一种映射这个映射关系实际上有两种作用&#xff1a;1、把 U…

Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)

好吧&#xff0c;这个题目我也想了很久&#xff0c;不知道如何用最简单的几个字来概括这篇文章&#xff0c;原本打算取名《Angular单页面应用基于Ocelot API网关与IdentityServer4ASP.NET Identity实现身份认证与授权》&#xff0c;然而如你所见&#xff0c;这样的名字实在是太…

【翻译】.NET 5 Preview 1 发布

.NET 5 Preview 1 发布去年年底,我们发布了.NET Core 3.0和3.1.这些版本添加了桌面应用程序模型Windows Forms(WinForms)和WPF,ASP.NET Blazor用于构建SPA应用程序和用于构建分布式应用和服务的gRPC模板、用于与gRPC对话丰富的客户端代码生成、REST API服务等等.我们很高兴看到…

Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(二)

上文已经介绍了Identity Service的实现过程。今天我们继续&#xff0c;实现一个简单的Weather API和一个基于Ocelot的API网关。回顾《Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权&#xff08;一&#xff09;》Weather APIWeather API实现非常简单&#xf…