消息抽象层设计和实现-OSS.DataFlow
前面已经介绍了消息生产消费中间类库(OSS.DataFlow)的简单使用,这篇主要介绍内部的设计实现。主要内容包含:
1. 消息生产消费的抽象设计。
2. 具体使用示例
一. 消息生产消费的抽象设计。
需要首先强调的是,这里的生产消费抽象主要在业务使用层面,抛开具体的RabbitMQ之类的消息队列产品。可能说起来比较模糊,我们先看下常见的业务调用消息队列的情况:
上边是一个常见的通过消息队列将业务异步拆解的模型,按道理结构已经十分简单了,特别是对于一个相对稳定的业务,代码基本变动不大的情况下,这个模型基本足够了。不过对于一个爱折腾的开发人,不玩点花里胡哨的,存在感就没了,经过各种假设论证之后,终于找到了这么几个不满意的地方:
1. 开发,测试,生产,都需要搭建对应的Rabbit实例,特别是开发测试环境抢消息,再加上多人开发,大麻烦可能没有,但小麻烦一定是不断的。
2. 业务代码中,直接调用了具体消息队列的产品,当某一个模块消息量快速上升,无法局部切换队列产品。(当然你也可以切分出独立的服务,但是耗时,代价相对较大)。
3. 对于同一解决方案内的异步消息,或多或少的会出现生产消息调用和消费消息调用代码分散(比如用户登录后添加日志)。
4. 当前的项目代码依赖外部消息队列或者数据库(如果公司偏项目型,新项目无法轻装上阵)
以上臆测仅个人偏见,仅供参考。在我的角度,我希望在业务调用消息中转的过程中,需要面向的是接口,在需要的时候适配即可,所以我尝试添加一个轻简的中间层。
这个中间层第一件事就是隔离,草图设计如下:
通过全局 DataFlowFactory 能够创建消息发布者(IDataPublisher),并能够注入订阅者(IDataSubscriber) ,业务层只需要通过 IDataPublisher,IDataSubscriber 接口交互,和具体消息存储设施脱离。顺着这个思路,当业务需要生产写入消息时,创建发布者,并通过发布者写入消息,并完成订阅者的回调,这个环路即可完成。
现在只需要解决两个问题:
1. 创建的发布者,如何实现不同场景的扩展。
2. 如何完成对应的订阅者(支持同一消息类型,多个订阅者)的回调。
这里我引入一个全局管理对象(DataFlowManager),内部的调用过程图示如下:
在 DataFlowManager 中提供了 PublisherProvider 公开属性,可用来扩展不同消息设施的发布者实现。同时,提供了 NotifySubscriber 方法,作为已注册消息订阅者的统一触发入口(内部完成了多个订阅者的调度,当然如果针对特殊消费者调用,用户也可以跳过注册订阅者,自由实现订阅处理)。
通过上边的整个过程,完全实现了消息中间层的功能,以插件的形式将具体的消息设施在程序的全局入口注入,这样就可以针对不同环境不同业务模块(入口的参数 source_name 控制)做定制化。同时,在大多数的项目中(包括在开发环境中)并无需立即使用独立的消息设施,所以在中间件的内部,提供了一个默认的内存消息队列实现,这样也保证了类库的即引即用,扩展后的图示如下:
根据上边的过程图可以看出,内部的默认队列,和外部队列所处统一层级,当没有提供用户自定义 PublisherProvider时(或者Provider 返回的 DataPublisher为空),系统会执行内部的默认队列实现。
二. 具体使用示例
上边展示了内部设计,这里介绍具体的代码使用层面,看在实际的使用中是如何简化内敛整个消息的处理。
1. 业务侧调用:
上边演示了消息Key为 “ P-S-Msg ” ,有两个订阅者(这里使用了委托方法,也可以传入继承IDataSubscriber<MsgData> 接口的实例),并且创建了一个名为 _publisher 的发布者(如果没有注册其他消息存储适配实现,会走默认内部消息队列实现,即创建一个名为 NewSource 的队列)。除了上边的使用方式,有些时候我们的生产和消费代码都是同一个服务内部,比如用户登录和添加登录日志,这个时候提供了一个更简单的方式:
可以看出,具体的业务代码相对很清晰,不需要关注具体的消息底层实现,或者什么触发方式(定时,webhook或者内部消费线程)。而这些内容全部转移到全局模块插件化适配。
二. 消息的底层适配:
上边的代码,自定义了一个 CustomMsgStorage 消息存储适配器,并在全局初始化时,赋值给 DataFlowManager.PublisherProvider ,在这个适配器里,约定了当 source_name 等于 CustomStorageQueue 时返回消息发布者 CustomMsgStoragePublisher,当然这个具体实现可以替换成 RabbitMQ,Redis,Mysql 等等,当消息实际消费触发时,调用 DataFlowManager.NotifySubscriber() 方法即可,在上边的测试用例里,我简化了这个过程,直接调用,实际场景根据情况调整即可(比如放在RabbitMQ的消费监控线程,或者读取Mysql数据的定时任务中)。
简单来说,DataFlowFactory处理业务使用接口(通过 msgkey 关联生产者和消费订阅者),DataFlowManager 控制具体的消息适配(通过 source_name 来控制底层适配), 基本解决了前面我所顾虑的问题。
如果你已经看到这里,并且感觉还行的话可以在下方点个赞,或者也可以关注我的公总号(见二维码)
消息抽象层设计和实现-OSS.DataFlow的更多相关文章
- SDK接入(U8SDK)——SDK抽象层的设计
上一篇文章,我们总体地分析并设计了一套高效的SDK接入方案,也罗列出这套方案,我们需要完成的工作.这里再罗列并回顾下: 1.统一抽象的SDK接入框架 2.各个SDK接入实现 3.一键打包工具 4.统一 ...
- 事件消息生产消费中间件-OSS.DataFlow
系统重构解耦的过程涉及不同领域服务分拆,或同一服务下实时响应部分和非响应部分分拆,分解后的各部分通过异步消息的流转传递,完成整体的业务逻辑,但是频繁的在业务层面直接调用不同消息队列的SDK,个人感觉不 ...
- Java消息系统简单设计与实现
前言:由于导师在我的毕设项目里加了消息系统(本来想水水就过的..),没办法...来稍微研究研究吧..简单简单... 需求分析 我的毕设是一个博客系统,类似于简书这样的,所以消息系统也类似,在用户的消息 ...
- 【开源】OSharp框架解说系列(5.1):EntityFramework数据层设计
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- ENode 1.0 - 消息队列的设计思路
开源地址:https://github.com/tangxuehua/enode 上一篇文章,简单介绍了enode框架内部的整体实现思路,用到了staged event-driven architec ...
- enode框架step by step之消息队列的设计思路
enode框架step by step之消息队列的设计思路 enode框架系列step by step文章系列索引: enode框架step by step之开篇 enode框架step by ste ...
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 1
现在,如果你已经能熟练地使用MySQL客户端软件来操作数据库中的数据,就可以开始学习如何使用PHP来显示和修改数据库中的数据了.PHP提供了标准的函数来操作数据库.在PHP 5以上的版本中可以使用My ...
- 网络编程之网络架构及其演变过程、互联网与互联网的组成、OSI七层协议、socket抽象层
目录 网络架构及其演变过程 单机架构 CS架构 BS架构 BS架构和CS架构的区别 C/S架构的优缺点: B/S架构的优缺点: 互联网与互联网的组成 互联网的组成(教科书版) 互联网的组成(科普版) ...
- redis源码分析(二)-rio(读写抽象层)
Redis io抽象层 Redis中涉及到多种io,如socket与file,为了统一对它们的操作,redis设计了一个抽象层,即rio,使用rio可以实现将数据写入到不同的底层io,但是接口相同.r ...
随机推荐
- 从零入门 Serverless | SAE 的远程调试和云端联调
作者 | 弈川 阿里巴巴云原生团队 导读:本节课程包含三部分内容,前两个部分简单介绍远程调试以及端云联调的原理,最后在 Serverless 应用引擎中进行实际演示. 经过之前课程的学习,相信大家对于 ...
- Appium iOS 原理
一.iOS Appium 原理 1.1 iOS 9.3 系统之前自动化测试 1.1.1 Native 自动化 这是 iOS 9.3 系统之前自动化测试的架构模式.通过 Android Appium 原 ...
- Java(26)集合一Collection
来源:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228419.html 博客主页:https://www.cnblogs.com/testero ...
- vps实现私人代码托管并用nginx部署hexo
个人博客 原本我的博客是通过github pages搭建的,但由于一些众所周知的原因,即使套上了CDN依旧是访问状态令人堪忧,经常会造成各种各样的问题,并且由于不存在服务器也不好进行进一步的管理,更不 ...
- 关于tkinter
tkinter介绍 tkinter是python自带的GUI库,是对图形库TK的封装tkinter是一个跨平台的GUI库,开发的程序可以在win,linux或者mac下运行 组件概念 一个窗口中任意内 ...
- BUAA2020软工作业(二)——对软件工程的初步理解
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 进一步提高自己的编码能力,工程能力 这个作业在哪个具体方面帮助 ...
- [调试笔记] 晚测5 T1 容易题
众所周知,sbwzx在考试一结束就嚷嚷T1是个sb题.那他为什么调了2小时才调出来呢?快和小编一起看看吧. Sb题:指除了sbwzx别人都能做出来的题 1.CE:震惊!sbwzx竟然连map都不会用, ...
- BZOJ4919[Lydsy1706月赛]大根堆-------------线段树进阶
是不是每做道线段树进阶都要写个题解..根本不会写 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...
- 安装hexo博客
前言 ** 跟着步骤一步一步来进行安装 ** 准备环境:node.js和包管理器npm 1:查看包文件 接着安装 淘宝镜像源 sudo这个需要添加获取文件夹访问权限 sudo npm install ...
- Less-5闯关失败
进行第五关的通关还是用之前的方式进行测试以及判断是什么类型的注入.通过判断我们不难发现是字符型注入.但是出了问题,我们会发现按照原来的步骤进行注入都会返回"You are in " ...