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");
        }
    }

关于服务总线的实现方式

  1. RedisBus基于redis进行存储,事件发布后,所有相关处理程序被回调,要求事件和处理程序是可序列化的
  2. MemoryBus基于应用服务器缓存进行存储,所有相关处理程序被回调,集群环境不是很适合
  3. IoCBus基于redis作为事件字典,处理程序由IoC容器进行注入,使用场合更广

IoCBus实现思想与组成

  1. 应该有一个存储事件与处理程序对应关系的字典
  2. 字典应该被持久化到中间件里
  3. 应该有个容器,去管理字典值与处理程序的关系

代码实现

数据变更的定义

     /// <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跨平台~服务总线_事件总线的重新设计,如需转载请自行联系原博主。

时间: 2024-10-24 12:21:32

DotNetCore跨平台~服务总线_事件总线的重新设计的相关文章

DotNetCore跨平台~文章索引~永久更新

本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet core越来越好,希望2.0正式版快点出来! 我们的框架应该是基于组件化的! 我们的系统应该是基于微服务化的! 我们的部署,应该是基于自动化的! DotNetCore跨平台目录 DotNetCore跨平台~Startup类的介绍(2016-05-31 16:25) Linux~centos上安装.

nest系列-event事件总线

设计思想 以系统思维为外部提供对外异步事件通知 支持系统间的异步事件请求,由分布式消息中间件提供 支持系统内的同步事件请求,由内部观察者模型提供(单线程) 通过事件总线统一发起事件及注册事件 通过可配置的扩展为事件提供消息通道 可通过插件方式为指定的消息中间件提供消息提供者 异步事件通过消息标识来提供消费者幂等性 异步事件支持最终一致性,即当工作单元的实体提交成功后再发起异步消息的提交,如果异步提交失败使用补偿机制重发消息 设计草图 数据流程 发起事件 应用程序通过事件总线服务发布事件,发布服务

Java事件总线编程初探

Why? 在平时写代码的过程中,我们需要实现这样一种功能:当执行某个逻辑时,希望能够进行其他逻辑的处理.最粗暴的方法是直接依赖其他模块,调用该模块的相应函数或者方法.但是,这样做带来一些问题. 模块间相互依赖,耦合度高.以下订单为例,订单提交后需要进行支付以及进行一些其他处理,如发邮件等操作.相关的代码可能是这样.可以看到:订单模块依赖了支付服务以及用户服务. 维护困难.由于模块间相互依赖,当需要修改订单逻辑时则需要修改submitOrder方法的源代码,而某些时候可能无法修改.再者,如果有多个

Android事件总线分发库EventBus3.0的简单讲解与实践

Android事件总线分发库EventBus的简单讲解与实践 导语,EventBus大家应该不陌生,EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅.以及将发送者和接收者解耦.反正能帮助我们快速开发,这个确实是个好东西,其实鸿洋大神已经对源码作了一个较全面的剖析了 Android EventBus源码解析 带你深入理解Ev

android事件总线

如果你不知道事件总线是什么,那么没有关系,下面我们先来看这么一个场景: 你是否在开发的过程中遇到过想在Activity-B中回调Activity-A中的某个函数,但Activity又不能手动创建对象来设置一个Listener什么的? 你是否想在某个Service中想更新Activity或者Fragment中的界面? 等等之类的组件之间的交互问题-- 一经思考,你会发现Android中的Activity, Fragment, Service之间的交互是比较麻烦的,可能我们第一想到的是使用广播接收器

Guava - EventBus(事件总线)

Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计. 不再多的废话,直奔Guava EventBus主题.首先Guava为我们提供了同步事件EventBus和异步实现AsyncEventBus两个事件总线,他们都不是单例的,官方理由是并不想我们我们的使用方式.当然如果我们想其为单例,我们可以很容易封装它,一个单例模式保证只创建一个实例就对了. 下面

DotNetCore跨平台~聊聊中间件

在进行.net core平台之后,我们如果希望在请求过程中添加一些事件是非常容易的,你可以把这些事件做成一个中间件Middleware,然后这些中间件就会以Http pipeline的管道方式进行相应,并且它们就像是一个职责链,从你定义的第一个中间件开始,一个一个向下传递,直到最后一个中间件完成为止! 前几天我写了在.net core里实现模块化服务,DotNetCore跨平台~组件化时代来了 主要是将我们定义的组件添加到IServiceCollection集合里,然后在程序启动后去注册它们,而

DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化

在DotNetCore出来之后,同时也使用了quartz进行调度中心的设计,将它做到docker里方便部署,在之前的quartz版本里支持配置文件的方式,而现在不支持了,我们应该去想一下,为什么不去支持配置文件?当然大叔也为配置文件设计了支持的方式,但我们还是应该想想作者为什么不去支持配置? 热插拔,服务发现? 和上面两个概念可能有点关系,热插拔很容易理解,就是把dll模块放到正在运行的项目时,它可以直接启动,这个功能对调度中心来说,很是必要,因为你可能需要按着不同的功能设计一些服务job,而这

DotNetCore跨平台~性能测试~可以放心使用了

使用dotnetCore发布站点后,它的处理请求能力不逊色IIS等大型服务的能力,号称每秒能处理115万个请求,太牛X了也. 先看看它支持的数据库 以下主流数据库都是为支持的 Microsoft SQL Server SQLite Npgsql (PostgreSQL) MySQL Microsoft SQL Server Compact Edition IBM Data Servers InMemory (for testing) 再看看老外测试出来的结果 ASP.NET Core – 230