一.系统描述

嗨,好久不见各位老哥,最近有点懒,技术博客写的太少了,因为最近在写小说,写的顺利的话说不定就转行了,哈哈哈哈哈哈哈哈哈。

今天要介绍的是基于.Net Core的定时任务调度和消息队列管理系统。相信大家对这两个肯定都已经很熟悉了,在开发过程中,这两个组件扮演了不可或缺的角色:

消息队列帮助我们进行 ”解耦“、”异步“、”削峰“

定时任务帮助我们进行 "后台"、”监控"、“补偿"

定时任务调度系统大家都介绍过很多次了,园子里的很多文章我也都拜读过,我相信大家实际的工作中肯定也都在频繁的使用它。目前主流的组件有 Quartz和Hangfire两种,在两者的选择上来说建议大家熟悉哪个用哪个就可以,Hangfire是自带UI管理界面的,所以如果想直接接入系统并且不想再进行二次开发做UI,可以直接选择Hangfire。

因为我对于Quartz更熟悉,所以本系统的定时任务调度基于Quartz开发,消息队列基于RabbitMQ,同时有一套UI,用于可视化操作定时任务调度和管理消息队列配置。

本系统是开发自用的,实际是公司工作中使用的系统,我自己私下里重写了一套后台代码,但是UI还是公司的那一套,因为是自用,所以无法达到直接开箱即用的效果,写这篇的目的只是希望分享两者的使用方式和场景,帮助各位在遇到相同应用场景的问题时能够有更多解决思路。

二.功能介绍

1.MQ界面化动态配置,对代码几乎无入侵。(当然你还是需要引用nuget用来Publish消息的)

2.提供定时任务调度功能。(基于Quartz,可以精确到秒,执行方式包括接口、sql脚本、elk)

3.基于数据库脚本的异常数据监控。(通过定时任务调度系统执行监控的sql脚本)

3.自动补偿。(当异常数据通过sql脚本监控出来后,发送MQ到指定消费接口进行数据处理)

三、系统架构介绍

整个系统包括六部分:

1. MI.MessageQueue:消息队列基础组件,就是我们用来操作RabbitMQ的一系列方法。

2.MI.MQStationServer:消息队列管理服务,提供包括消息队列的增删改查接口,消费MQ消息。

3.MI.Service.Blade:定时任务调度管理服务,提供定时任务相关的一系列操作接口。

4.MI.Biz.MQStation:消息队列windows服务,用于消费MQ,主要是建立相关的消息消费者,并转发消息到消息队列管理服务。

5.MI.Biz.Blade:定时任务windows服务,用于创建及转发相应的任务,真正的执行在MI.Service.Blade服务。

6.MI.Monitor.Web:UI管理界面,以上两者所有的增删改查都在这里。

以下是定时任务调度系统间的交互:

简单描述一下,用户在MI.Monitor.Web系统中通过界面化的操作创建定时任务,其会调用API接口也就是MI.Service.Blade服务,将操作的数据写入数据库,对于增删改,数据库写入完成后会发送一条MQ消息,Windows服务MI.Biz.Blade收到MQ消息后,根据消息中的数据添加或更改Quartz配置信息,对于定时任务Quartz完全基于代码动态化创建和删除。这样交互的好处一方面是解耦,这个比较明显,这里解耦带来的一个好处是异常隔离,本身三者之间的分工不同,对于发生问题的一方只在内部消化;第二点好处是方便横向扩展,无论是Windows服务还是API都可以根据自身的负载动态加减机器。当然,对于WIndows服务我们要做集群,通过Zookeeper可以实现,防止单点故障。

以下是消息队列系统的交互:

看起来和上面的定时任务调度交互好像差不多,不过这个地方的麻烦点其实在于基础组件的编写,就是MI.MessageQueue里面的一系列RabbitMQ操作,目前支持单消息、批量消息、延时消息,延时消费需要借助RabbitMQ官方提供的 ”rabbitmq_delayed_message_exchange“插件,有需要的话可以去了解以下,官方的API支持该操作。

还是照例描述一下消息队列的数据交互流程,用户在MI.Monitor.Web系统中通过界面化的操作创建或者更新消息队列,其会调用API接口也就是MI.MQStationServer服务,将操作的数据写入数据库,写入完成后会创建交换器(Exchange),然后发送MQ消息,Windows服务MI.Biz.MQStation收到消息后,将队列和RouteKey绑定到对应的交换器,同时创建消费者,绑定监听回调,该回调只是当作一个转发,收到消息后会通过接口将数据发送到MI.MQStationServer服务,根据在UI中配置的RouteKey和要消费的接口进行消费处理。

消息队列这样设计的好处之一是解耦,同时异常隔离,这个就不说了,大家都明白;当然最重要的好处就是可以动态扩展,消费压力大,多启动几个windows服务和API服务,就是多加些消费者,这个理解起来也比较简单。

四、优化和展示

对于消息队列系统目前还在开发中的功能是消息的数量统计,该系统是支持查看每个队列未消费的消息量,但是还没开发完成,这边博文会一直更新的。

下面是系统的部分界面:

定时任务界面:

.Net Core 商城微服务项目系列(十五): 构建定时任务调度和消息队列管理系统的更多相关文章

  1. .Net Core 商城微服务项目系列(五):使用Polly处理服务错误

    项目进行微服务化之后,随之而来的问题就是服务调用过程中发生错误.超时等问题的时候我们该怎么处理,比如因为网络的瞬时问题导致服务超时,这在我本人所在公司的项目里是很常见的问题,当发生请求超时问题的时候, ...

  2. .Net Core 商城微服务项目系列(一):使用IdentityServer4构建基础登录验证

    这里第一次搭建,所以IdentityServer端比较简单,后期再进行完善. 1.新建API项目MI.Service.Identity,NuGet引用IdentityServer4,添加类InMemo ...

  3. .Net Core 商城微服务项目系列(十四):分布式部署携程Apollo构建配置中心

    一.开场白 在系统设计里我们有很多配置希望独立于系统之外,而又能够被系统实时读取.但是在传统的系统设计里,配置信息通常是耦合在系统内的,比如.net里通常会放在App.config或者web.conf ...

  4. .Net Core 商城微服务项目系列(十二):使用k8s部署商城服务

    一.简介 本篇我们将会把商城的服务部署到k8s中,同时变化的还有以下两个地方: 1.不再使用Consul做服务的注册和发现,转而使用k8s-dns来实现. 2.不再使用Ocelot作为业务网关,使用T ...

  5. .Net Core 商城微服务项目系列(八):购物车

    最近加班有点多,一周五天,四天加班到11点+,心很累.原因是我当前在的这个组比较特殊,相当于业务的架构组,要为其它的开发组提供服务和监控.所以最近更新的也少,不过这个元旦三天假应该会更新三篇. 这篇是 ...

  6. .Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器

    当我们使用微服务架构之后,紧接而来的问题便是服务之间的程序集引用问题,可能没接触过的同学不太理解这句话,都已经微服务化了为什么还要互相引用程序集,当然可以不引用.但是我们会有这样一种情况,我们的每个接 ...

  7. .Net Core 商城微服务项目系列(七):使用消息队列(RabbitMQ)实现服务异步通信

    RabbitMQ是什么,怎么使用我就不介绍了,大家可以到园子里搜一下教程.本篇的重点在于实现服务与服务之间的异步通信. 首先说一下为什么要使用消息队列来实现服务通信:1.提高接口并发能力.  2.保证 ...

  8. .Net Core 商城微服务项目系列(十):使用SkyWalking构建调用链监控(2019-02-13 13:25)

    SkyWalking的安装和简单使用已经在前面一篇介绍过了,本篇我们将在商城中添加SkyWalking构建调用链监控. 顺带一下怎么把ES设置为Windows服务,cd到ES的bin文件夹,运行ela ...

  9. .Net Core 商城微服务项目系列(十三):搭建Log4net+ELK+Kafka日志框架

    之前是使用NLog直接将日志发送到了ELK,本篇将会使用Docker搭建ELK和kafka,同时替换NLog为Log4net. 一.搭建kafka 1.拉取镜像 //下载zookeeper docke ...

随机推荐

  1. Fire Balls 05——子弹的命中及后续效果

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  2. ElementUI使用v-if控制tab标签显示遇到的Duplicate keys detected: 'xxx'问题

    今天工作遇到一个问题: 需求背景:页面中有几个tab,需要根据登录用户的权限控制tab标签的显示与隐藏 . <el-tabs @tab-click="handleClick" ...

  3. 探索JAVA并发 - 终于搞懂了sleep/wait/notify/notifyAll

    > sleep/wait/notify/notifyAll分别有什么作用?它们的区别是什么?wait时为什么要放在循环里而不能直接用if? ## 简介 首先对几个相关的方法做个简单解释,Obje ...

  4. 【HDU5409】CRB and Graph 边双联通 子树最值

    HDU # 题意 有一个简单图,n个点,m条边.对于每条割边,求出删去这条边后,在两个联通块中各取一个u,v.使得u<v,并且u尽量大而v尽量小. # 思路 求出边双联通是肯定的. 答案的限制条 ...

  5. HDU4578 线段树(区间更新 + 多种操作)和平方,立方

    参考:https://www.cnblogs.com/H-Vking/p/4297973.html 题意: 虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,对着别人的ac代码debug了一 ...

  6. POJ 1797-Heavy Transportation-dijkstra小变形和POJ2253类似

    传送门:http://poj.org/problem?id=1797 题意: 在起点和终点间找到一条路,使得经过的边的最小值是最大的: 和POJ2253类似,传送门:http://www.cnblog ...

  7. 区间dp专题

    HDU4283You Are the One区间dp, 记忆话搜索运行时间:   #include <iostream> #include <cstdio> #include ...

  8. HZNU 2019 Summer training 6 -CodeForces - 622

    A - Infinite Sequence  CodeForces - 622A 题目大意:给你一个这样的数列1,1,2,1,2,3,1,2,3,4,1,2,3,4,5....就是从1~n排列(n++ ...

  9. CF - 1130 E Wrong Answer

    PS:换了一种方式 希望大家喜欢 2333 /** code by: zstu wxk time: 2019/03/01 Problem Link: http://codeforces.com/con ...

  10. @override 重写 与重载

    方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现.重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多 ...