事件消息生产消费中间件-OSS.DataFlow
系统重构解耦的过程涉及不同领域服务分拆,或同一服务下实时响应部分和非响应部分分拆,分解后的各部分通过异步消息的流转传递,完成整体的业务逻辑,但是频繁的在业务层面直接调用不同消息队列的SDK,个人感觉不够简洁,最近开源一个中间件OSS.Dataflow,希望能帮到看到的同学。
OSS.Dataflow主要实现异步消息传递的过程抽象,在业务层面提供消息发布订阅的统一抽象接口,在业务逻辑分支之间,以简单的调用完成消息的传递,和具体的消息存储触发实现无关。同时,在底层的存储和触发层面提取接口,能够在系统的全局适配具体的消息基础设施。(在这些接口之上,还实现了事件处理器,通过消息的重复投放,实现事件执行的容错补充机制,这个后边文章再介绍,源代码单元测试有示例。)
一. 消息业务侧使用
OSS.Dataflow 的代码可以通过Gitee和GitHub获取,使用时可以通过Nuget直接安装,也可以通过命令行:Install-Package OSS.DataFlow
组件的使用非常简单,只需要关注:
- 消息发布者接口,由组件注册时返回,供业务方法调用传入消息体。
- 消息订阅(消费)者接口实现或委托方法,在组件注册时传入。
具体示例:
- 消息的发布订阅独立调用示例
// 全局初始化,注入订阅者实现
const string msgPSKey = "Publisher-Subscriber-MsgKey";
DataFlowFactory.RegisterSubscriber<MsgData>(msgPSKey, async (data) =>
{
// 当前通过注入消费的委托方法,也可通过接口实现
// DoSomething(data);
return true;
}); // 获取发布者接口
private static readonly IDataPublisher publisher = DataFlowFactory.CreatePublisher(); // 业务方法中发布消息
await publisher.Publish(msgPSKey,new MsgData() {name = "test"});
2. 消息的流式调用示例
// 直接注册消费实现并获取消息发布接口
private static readonly IDataPublisher _delegateFlowpusher =
DataFlowFactory.RegisterFlow<MsgData>("delegate_flow",async (data) =>
{
// 当前通过注入消费的委托方法,也可通过接口实现
// DoSomething(data);
return true;
}); // 业务方法中发布消息
await _delegateFlowpusher.Publish("normal_flow",new MsgData() {name = "test"});
如上,只需要获取发布者,并注入消费实现,即可完成整个消息的异步消费处理,同一个消息key可以注册多个消费实现,当有消息进入消费时,会并发处理。
二. 消息底层存储适配扩展
前边介绍了业务接口的使用,和具体消息队列或数据库等隔离,这是对接业务层面的使用。因为业务场景不同,不同的项目对消息的响应速度和处理机制又各有需求,所以 OSS.DataFlow 同样提供了对接消息产品的扩展接口,方便使用者适配已有消息基础设施。
1. 消息存储适配接口
对于事件消息处理,需要关注两件事情:接收存储 和 消费触发。在类库中提供了 DataFlowManager 消息流管理类,用户可以通过实现IDataPublisherProvider接口,完成具体的存储实现。
同时在不同的消息产品触发消费时(比如数据库定时任务或者RabbitMQ消费), 调用通知方法(NotifySubscriber ),来触发通过类库注册的具体的业务订阅处理。
// 消息流核心部件管理者
public static class DataFlowManager
{
/// <summary>
/// 自定义 数据流发布(存储)实现的 提供者
/// </summary>
public static IDataPublisherProvider PublisherProvider { get; set; } /// <summary>
/// 通过自定义消息触发机制通知订阅者
/// 调用时请做异常拦截,防止脏数据导致 msgData 类型错误
/// </summary>
/// <param name="msgDataKey"></param>
/// <param name="msgData">消息内容,自定义触发时,请注意和注册订阅者的消费数据类型转换安全</param>
/// <returns></returns>
public static Task<bool> NotifySubscriber(string msgDataKey, object msgData)
{
....
}
}
关于 IDataPublisherProvider
public interface IDataPublisherProvider
{
/// <summary>
/// 数据发布者
/// </summary>
/// <param name="option"></param>
/// <returns> 返回消息发布接口实现 </returns>
IDataPublisher CreatePublisher(DataPublisherOption option);
} /// <summary>
/// 数据的发布者
/// </summary>
public interface IDataPublisher
{
/// <summary>
/// 推进数据(存储具体消息队列或者数据库实现)
/// </summary>
/// <param name="dataKey"></param>
/// <param name="data"></param>
/// <returns>是否推入成功</returns>
Task<bool> Publish<TData>(string dataKey,TData data);
}
可以看到 IDataPublisher 接口负责具体的存储实现,可以根据 DataPublisherOption 的 source_name 业务属性实现对不同业务需求返回不同的具体实现。
2. 默认实现介绍
借助.Net 自身的内存消息队列,在类库中提供了默认的内部消息存储转发实现(内存级别),使用者可以自行实现扩展相关接口并进行全局配置。
内置的.Net Core消息队列, 设置了默认1个队列,最大并发为32线程。 如果需要可以通过设置DataPublisherOption的source_name,类库将会为每个source_name 创建独立的内存队列。
如果你已经看到这里,并且感觉还行的话可以在下方点个赞,或者也可以关注我的公总号(见二维码)

事件消息生产消费中间件-OSS.DataFlow的更多相关文章
- NSQ源码剖析——主要结构方法和消息生产消费过程
目录 1 概述 2 主要结构体及方法 2.1 NSQD 2.2 tcpServer 2.3 protocolV2 2.4 clientV2 2.5 Topic 2.6 channel 3 启动过程 4 ...
- Spring整合ActiveMQ,实现队列主题消息生产消费
1.引入依赖 pom.xml 1 <!-- activemq --> 2 <dependency> 3 <groupId>org.springframework&l ...
- 消息抽象层设计和实现-OSS.DataFlow
前面已经介绍了消息生产消费中间类库(OSS.DataFlow)的简单使用,这篇主要介绍内部的设计实现.主要内容包含: 1. 消息生产消费的抽象设计. 2. 具体使用示例 一. 消息生产消费的抽象设计. ...
- Kafka创建&查看topic,生产&消费指定topic消息
启动zookeeper和Kafka之后,进入kafka目录(安装/启动kafka参考前面一章:https://www.cnblogs.com/cici20166/p/9425613.html) 1.创 ...
- Dyno-queues 分布式延迟队列 之 生产消费
Dyno-queues 分布式延迟队列 之 生产消费 目录 Dyno-queues 分布式延迟队列 之 生产消费 0x00 摘要 0x01 前情回顾 1.1 设计目标 1.2 选型思路 0x02 产生 ...
- kafka生产消费原理笔记
一.什么是kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性 ...
- Spring Cloud Stream如何处理消息重复消费?
最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题.通过沟通与排查下来主要还是用户对消费组的认识不够.其实,在之前的博文 ...
- ActiveMQ消息的消费原理
消费端消费消息: 在 初识ActiveMQ 中我提到过,两种方法可以接收消息,一种是使用同步阻塞的ActiveMQMessageConsumer#receive方法.另一种是使用消息监听器Messag ...
- kafka_2.11-0.8.2.1+java 生产消费程序demo示例
Kafka学习8_kafka java 生产消费程序demo示例 kafka是吞吐量巨大的一个消息系统,它是用scala写的,和普通的消息的生产消费还有所不同,写了个demo程序供大家参考.kaf ...
随机推荐
- mysql where in 数组解决小tips
由于sql语法要求,不可在in后面直接连数组,若数组形式下,则需要转换成逗号隔开的字符串 <?php$arr = array(1,2,3,4,5);$arr_string= join(',', ...
- vue项目中的element-ui地区级联选择器加详细地址push到对象中不显示的问题
想要实现级联选择器el-cascader和输入框el-input共同组成的详细地址,添加数据时弹出el-drawer嵌套el-form弹窗,然后在el-form添加数据提交后push到el-table ...
- windows terminal+wsl+neovim配置过程杂记
长期记录,草稿 coc依赖于node,直接sudo apt intsll node得到的版本是10.x,无法满足要求, 这篇博客介绍了安装新版node的方法https://www.cnblogs.co ...
- 一个神秘的oj2093 花园的守护之神(最小割)
给定一张无向图,你每次可以将一条路的权值增加1,询问最少增加多少次才会使得\(s->t\)的最短路改变 QwQ一看到这个题,我就用种最小割的感觉 我们可以把最短路上的点取出来,然后做最小割呀!! ...
- SpringBoot-自动装配2
配置文件到底能写什么?怎么写? SpringBoot官方文档中有大量的配置,直接去记忆的话,好像不是我们程序员的行事风格! 分析自动配置原理 能自动配置的组件一般都有命名为下面规则的两个类: xxxx ...
- vue基本指令与脚手架基本配置
脚手架(@vue/cli)创建项目启动服务 1.创建项目 vue create 项目名字 2.启动项目 进入项目根目录,运行以下命令 yarn serve 3.脚手架目录代码分析 ├── node_m ...
- python常用功能
1. 获取昨天日期 引入datetime模块 import datetime def getYesterday(): today = datetime.date.today() #返回当前本地日期 # ...
- 初学Python “登录”案例 更新!!
更新内容:添加了登录次数,如果超过限制的次数,则提示账户被锁定,去某邮箱申请解锁账户! 此次仅把登录系统更新之后源代码放到这里,不在共享源文件在网盘了! 1 ''' 2 登录界面 3 ''' 4 5 ...
- 学习笔记-React的简单介绍&工作原理
一.React简单介绍 1.React起源于Facebook内部项目,与2013年5月 2.是一个用于构建用户界面的JavaScript库 二.React特点 1.声明式设计-React采用声明范式, ...
- 敏捷 Scrum Master 的難點
什麼是 Scrum Master? Scrum master 是一個團隊角色,負責確保團隊遵守敏捷方法和原則並符合團隊的流程和實踐. Scrum Master 促進敏捷開發團隊成員之間的協作.Scru ...