事件消息生产消费中间件-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 ...
随机推荐
- python二级 之 第 五套
1. 这里要注意输入的 就是列表 . [1,2,3] 2. 就是你要明白 random.seed() 产生随机种子# 与random.randint() 取 ...
- P6091-[模板]原根
正题 题目链接:https://www.luogu.com.cn/problem/P6091 题目大意 给出一个数\(p\),求出它的所有在\([0,p]\)的原根. 解题思路 原根的定义,\(\de ...
- 数据库的规范和SQL优化技巧总结
现总结工作与学习中关于数据库的规范设计与优化技巧 1.规范背景与目的 MySQL数据库与 Oracle. SQL Server 等数据库相比,有其内核上的优势与劣势.我们在使用MySQL数据库的时候需 ...
- FastAPI(45)- JSONResponse
背景 创建 FastAPI 路径操作函数时,通常可以从中返回任何数据:字典.列表.Pydantic 模型.数据库模型等 默认情况下,FastAPI 会使用 jsonable_encoder 自动将该返 ...
- hexo访问优化之--------gulp压缩
hexo访问优化之--------gulp压缩 hexo生成的博客是静态html页面,当有很多静态资源时,加载速度会非常慢,且github服务器在国外,导致网页加载速度非常差 gulp压缩 gulp是 ...
- 题解 CF961G 【Partitions】
题目传送门 题目大意 给出\(n,k\),以及\(w_{1,2,..,n}\),定义一个集合\(S\)的权值\(W(S)=|S|\sum_{x\in S} w_x\),定义一个划分\(R\)的权值为\ ...
- iOS能否自动扫描周边wifi信息并通过密码连接
能否获取系统wifi列表信息 不能,只能获取用户当前连接的wifi信息 https://developer.apple.com/forums/thread/112177 https://develop ...
- python中dump与dumps实现序列化
前言 使用中如果我们想把python可识别对象的dict类型的数据通过str类型写入文件或者存入变量中就需要用到dump与dumps 详解 dump 1.新建个dict文件,然后将dict文件存入一个 ...
- NX二次开发-调内部函数UGS::UICOMP_enum::set_width(int)更改BlockUI的枚举控件宽度
版本 NX11+VS2013 内容说明 这个内部函数的设置方法,我之前不会,是QQ群里的一位大佬分享出来的. 关于这块,我也百度搜了一下,找到了几个相关的. 1.直接手动修改BlockUI界面 在低版 ...
- 重磅!微软发布 vscode.dev,把 VS Code 带入浏览器!
早在 2019 年,当.dev顶级域名开放时,我们赶紧注册了vscode.dev.像许多购买.dev域名的人一样,我们不知道我们将用它做啥.反正,也占个坑吧! 将 VS Code 带入浏览器 直到今天 ...