DotNetCore跨平台~服务总线_事件总线的重新设计
理论闲话
之前在.netFramework平台用的好好的,可升级到.net core平台之后,由于不再需要二进制序列化,导致咱们的事件机制遇到了问题,之前大叔的事件一直是将处理程序序列化后进行存储的,处理存储的参数为事件源,一个事件源可以由多个处理程序订阅,当事件源被发布时,这些被序列化的代码段会被回调执行,这是大叔之前的思路,在RedisBus和MemoryBus里已经得到了实现,读过大叔源代码的同学应该有所了解了。
事件源和处理程序
/// <summary>
/// 事件源
/// </summary>
public class CreateUserCommand : BusData
{
public string UserName { get; set; }
} /// <summary>
/// 事件处理程序
/// </summary>
public class CreateUserCommandHandler : IBusHandler<CreateUserCommand>
{
public void Handle(CreateUserCommand evt)
{
LoggerFactory.CreateLog().Logger_Debug(evt.UserName);
Console.WriteLine("CreateUserCommandHandler");
}
}
关于服务总线的实现方式
- RedisBus基于redis进行存储,事件发布后,所有相关处理程序被回调,要求事件和处理程序是可序列化的
- MemoryBus基于应用服务器缓存进行存储,所有相关处理程序被回调,集群环境不是很适合
- IoCBus基于redis作为事件字典,处理程序由IoC容器进行注入,使用场合更广
IoCBus实现思想与组成
- 应该有一个存储事件与处理程序对应关系的字典
- 字典应该被持久化到中间件里
- 应该有个容器,去管理字典值与处理程序的关系
代码实现
数据变更的定义
/// <summary>
/// redis key
/// </summary>
const string ESBKEY = "IoCESBBus";
/// <summary>
/// redis事件字典
/// </summary>
IDatabase redis = RedisManager.Instance.GetDatabase();
/// <summary>
/// 模式锁
/// </summary>
private static object _objLock = new object();
/// <summary>
/// 对于事件数据的存储,目前采用内存字典
/// </summary>
private readonly IContainer container = new AutofacContainer();
事件的统一订阅
public void SubscribeAll()
{
var types = AssemblyHelper.GetTypesByInterfaces(typeof(IBusHandler<>));
Dictionary<string, List<string>> keyDic = new Dictionary<string, List<string>>();
foreach (var item in types)
{
if (!item.IsGenericParameter)
{ TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(item); foreach (var t in typeInfo.GetMethods().Where(i => i.Name == "Handle"))
{
//ioc name key
var eventKey = t.GetParameters().First().ParameterType.Name;
var key = t.GetParameters().First().ParameterType.Name + "_" + item.Name;
//eventhandler
var inter = typeof(IBusHandler<>).MakeGenericType(t.GetParameters().First().ParameterType);
container.Register(inter, item, key); if (keyDic.ContainsKey(eventKey))
{
var oldEvent = keyDic[eventKey];
oldEvent.Add(key);
}
else
{
var newEvent = new List<string>();
newEvent.Add(key);
keyDic.Add(eventKey, newEvent);
}
}
}
//redis存储事件与处理程序的映射关系
foreach (var hash in keyDic)
redis.HashSet(
ESBKEY,
hash.Key.ToString(),
JsonConvert.SerializeObject(hash.Value)); } }
事件的发布,相关处理程序会从容器中取出,并执行它们的Handler方法
public void Publish<TEvent>(TEvent @event)
where TEvent : class, IBusData
{
var keyArr = JsonConvert.DeserializeObject<List<string>>(redis.HashGet(ESBKEY, typeof(TEvent).Name));
foreach (var key in keyArr)
{
var item = container.ResolveNamed<IBusHandler<TEvent>>(key);
item.Handle(@event);
} }
说到这里,大叔的服务总线的IoC实现方式就算是完成了,经过测试后,在.net core上表现也很不错!
自己也骄傲一次,呵呵!
DotNetCore跨平台~服务总线_事件总线的重新设计的更多相关文章
- 【bird-java】分布式服务间的事件总线EventBus
什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...
- DotNetCore跨平台~文章索引~永久更新
本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...
- Autofac解耦事件总线
事件总线之Autofac解耦 事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线 ...
- RabbitMQ的事件总线
RabbitMQ的事件总线 在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系 ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...
- 浅入 ABP 系列(4):事件总线
浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...
- Android事件总线
Android中Activity.Service.Fragment之间的相互通信比较麻烦,主要有以下一些方法: (1)使用广播,发送者发出广播,接收者接收广播后进行处理: (2)使用Handler和M ...
- 事件总线(Event Bus)知多少
源码路径:Github-EventBus 简书同步链接 1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集 ...
随机推荐
- JS 一条原型链扯到底
在正文之前,首先要知道两点, 1.__proto__是每个js 对象的内置属性,而prototype 是函数的内置属性,也是一个对象. 2.所谓原型,指的就是每个函数对象的prototype属性. f ...
- socket.io搭配pm2(cluster)集群解决方案
socket.io与cluster 在线上系统中,需要使用node的多进程模型,我们可以自己实现简易的基于cluster模式的socket分发模型,也可以使用比较稳定的pm2这样进程管理工具.在常规的 ...
- Java IO流之文件流
一.文件流分类 二.FileInputStream 三.FileOutputStream 四.FileReader 五.FileWriter 六.文件流应用 1,复制或剪切文件 2,读取文件信息 应用 ...
- 腾讯AlloyTeam发布AlloyLever - 开发调试发布错误监控上报用户问题定位尽在1kb代码
AlloyLever [官网][Giuhub] 1kb(gzip)代码搞定开发调试发布,错误监控上报,用户问题定位. 支持错误监控和上报 支持 vConsole错误展示 支持开发阶段使用 vConso ...
- Spring 4学习——问题与注意事项(一)
1.Spring项目依赖的jar包有5个: 2.applicationContext.xml文件中,如下bean的property的name值对应的是HelloWorld类中的setter方法,即na ...
- WLAN高密无线网络部署的信道问题
WIFI信号的信道有两部分,其中2.4G频段有13个左右交叠的信道(14信道只在日本使用),其中只能找出3个相互不重合的信道(具体请参考文末的链接),最常用的就是1.6.11这三个,当然也可以使用其他 ...
- CSS都有哪些选择器?
派生选择器(用HTML标签申明) id选择器(用DOM的ID申明) 类选择器(用一个样式类名申明) 属性选择器(用DOM的属性申明,属于CSS2,IE6不支持,不常用,不知道就算了) 除了前3种基本选 ...
- C++数组概述
C++数组概述 基本概念 1. 数组是固定大小的一种复合类型 因为数组是固定大小,所以在编译期间就决定了基大小 数组的内存是连续(无论是一维数组还是多维数组) 2. 数组的特性 数组之间不允许拷贝和赋 ...
- RabbitMQ windows安装官方文档翻译!
RabbitMQ Windows安装和配置 下载地址 官网windows下载地址: http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/r ...
- Spring Web 配置文件加载路径问题
Spring: 定位 载入 注册 我们常用的加载context文件的方法有如下三个: 1.FileSystemXmlApplicationContext 这个方法是从文件绝对路径加载配置文 ...