Jaina

.NET 事件总线,简化项目、类库、线程、服务等之间的通信,代码更少,质量更好。‎

安装

Install-Package Jaina
dotnet add package Jaina

快速入门

我们在主页上有不少例子,这是让您入门的第一个:

  1. 定义事件订阅者 ToDoEventSubscriber
// 实现 IEventSubscriber 接口
public class ToDoEventSubscriber : IEventSubscriber
{
private readonly ILogger<ToDoEventSubscriber> _logger;
public ToDoEventSubscriber(ILogger<ToDoEventSubscriber> logger)
{
_logger = logger;
}
// 标记 [EventSubscribe(事件 Id)] 特性
[EventSubscribe("ToDo:Create")]
public async Task CreateToDo(EventHandlerExecutingContext context)
{
var todo = context.Source;
_logger.LogInformation("创建一个 ToDo:{Name}", todo.Payload);
await Task.CompletedTask;
}
}
  1. 创建控制器 ToDoController,依赖注入 IEventPublisher 服务:
[Route("api/[controller]/[action]")]
[ApiController]
public class ToDoController : ControllerBase
{
// 依赖注入事件发布者 IEventPublisher
private readonly IEventPublisher _eventPublisher;
public ToDoController(IEventPublisher eventPublisher)
{
_eventPublisher = eventPublisher;
}
// 发布 ToDo:Create 消息
[HttpPost]
public async Task CreateDoTo(string name)
{
await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));
}
}
  1. Startup.cs 注册 EventBus 服务:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 注册 EventBus 服务
services.AddEventBus(buidler =>
{
// 注册 ToDo 事件订阅者
buidler.AddSubscriber<ToDoEventSubscriber>();
});
// ....
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ....
}
}
  1. 运行项目:
info: Jaina.Samples.ToDoEventSubscriber[0]
创建一个 ToDo:Jaina

高级教程

1. 自定义事件源 IEventSource

Jaina 使用 IEventSource 作为消息载体,任何实现该接口的类都可以充当消息载体。

如需自定义,只需实现 IEventSource 接口即可:

public class ToDoEventSource : IEventSource
{
// 自定义属性
public string ToDoName { get; } /// <summary>
/// 事件 Id
/// </summary>
public string EventId { get; } /// <summary>
/// 事件承载(携带)数据
/// </summary>
public object Payload { get; } /// <summary>
/// 取消任务 Token
/// </summary>
/// <remarks>用于取消本次消息处理</remarks>
public CancellationToken CancellationToken { get; } /// <summary>
/// 事件创建时间
/// </summary>
public DateTime CreatedTime { get; } = DateTime.UtcNow;
}

使用:

await _eventPublisher.PublishAsync(new ToDoEventSource {
EventId = "ToDo:Create",
ToDoName = "我的 ToDo Name"
});

2. 自定义事件源存储器 IEventSourceStorer

Jaina 默认采用 Channel 作为事件源 IEventSource 存储器,开发者可以使用任何消息队列组件进行替换,如 Kafka、RabbitMQ、ActiveMQ 等,也可以使用部分数据库 Redis、SQL Server、MySql 实现。

如需自定义,只需实现 IEventSourceStorer 接口即可:

public class RedisEventSourceStorer : IEventSourceStorer
{
private readonly IRedisClient _redisClient; public RedisEventSourceStorer(IRedisClient redisClient)
{
_redisClient = redisClient;
} // 往 Redis 中写入一条
public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)
{
await _redisClient.WriteAsync(...., cancellationToken);
} // 从 Redis 中读取一条
public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)
{
return await _redisClient.ReadAsync(...., cancellationToken);
}
}

最后,在注册 EventBus 服务中替换默认 IEventSourceStorer

services.AddEventBus(buidler =>
{
// 替换事件源存储器
buidler.ReplaceStorer<RedisEventSourceStorer>();
});

3. 自定义事件发布者 IEventPublisher

Jaina 默认内置基于 Channel 的事件发布者 ChannelEventPublisher

如需自定义,只需实现 IEventPublisher 接口即可:

public class ToDoEventPublisher : IEventPublisher
{
private readonly IEventSourceStorer _eventSourceStorer; public ChannelEventPublisher(IEventSourceStorer eventSourceStorer)
{
_eventSourceStorer = eventSourceStorer;
} public async Task PublishAsync(IEventSource eventSource)
{
await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken);
}
}

最后,在注册 EventBus 服务中替换默认 IEventPublisher

services.AddEventBus(buidler =>
{
// 替换事件源存储器
buidler.ReplacePublisher<ToDoEventPublisher>();
});

4. 添加事件执行监视器 IEventHandlerMonitor

Jaina 提供了 IEventHandlerMonitor 监视器接口,实现该接口可以监视所有订阅事件,包括 执行之前、执行之后,执行异常,共享上下文数据

如添加 ToDoEventHandlerMonitor

public class ToDoEventHandlerMonitor : IEventHandlerMonitor
{
private readonly ILogger<ToDoEventHandlerMonitor> _logger;
public ToDoEventHandlerMonitor(ILogger<ToDoEventHandlerMonitor> logger)
{
_logger = logger;
} public Task OnExecutingAsync(EventHandlerExecutingContext context)
{
_logger.LogInformation("执行之前:{EventId}", context.Source.EventId);
return Task.CompletedTask;
} public Task OnExecutedAsync(EventHandlerExecutedContext context)
{
_logger.LogInformation("执行之后:{EventId}", context.Source.EventId); if (context.Exception != null)
{
_logger.LogError(context.Exception, "执行出错啦:{EventId}", context.Source.EventId);
} return Task.CompletedTask;
}
}

最后,在注册 EventBus 服务中注册 ToDoEventHandlerMonitor

services.AddEventBus(buidler =>
{
// 主键事件执行监视器
buidler.AddMonitor<ToDoEventHandlerMonitor>();
});

5. 自定义事件处理程序执行器 IEventHandlerExecutor

Jaina 提供了 IEventHandlerExecutor 执行器接口,可以让开发者自定义事件处理函数执行策略,如 超时控制,失败重试、熔断等等

如添加 RetryEventHandlerExecutor

public class RetryEventHandlerExecutor : IEventHandlerExecutor
{
public async Task ExecuteAsync(EventHandlerExecutingContext context, Func<EventHandlerExecutingContext, Task> handler)
{
// 如果执行失败,每隔 1s 重试,最多三次
await Retry(async () => {
await handler(context);
}, 3, 1000);
}
}

最后,在注册 EventBus 服务中注册 RetryEventHandlerExecutor

services.AddEventBus(buidler =>
{
// 主键事件执行监视器
buidler.AddExecutor<RetryEventHandlerExecutor>();
});

文档

您可以在主页找到 Jaina 文档。

贡献

该存储库的主要目的是继续发展 Jaina 核心,使其更快、更易于使用。Jaina 的开发在 Gitee 上公开进行,我们感谢社区贡献错误修复和改进。

许可证

Jaina 采用 MulanPSL-2.0 开源许可证。

Copyright (c) 2020-2021 百小僧, Baiqian Co.,Ltd.
Jaina is licensed under Mulan PSL v2.
You can use this software according to the terms andconditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
https://gitee.com/dotnetchina/Jaina/blob/master/LICENSE
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUTWARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.

.NET 事件总线,简化项目、类库、线程、服务等之间的通信,代码更少,质量更好。‎的更多相关文章

  1. RRiBbit,一个事件总线.基于spring配置不同服务通信!

    1.何为RRiBbit? *一种开源事件总线技术,能够让模块(组件)之间双向通讯,也被称为请求相应总线(request-response-bus),使用简单,相对其他框架来说,RRiBbit只需要加个 ...

  2. 通过Socket实现TCP编程,用户登录之服务器相应客户端,客户端和服务端之间的通信

    服务器端: 1.创建ServerSocket对象,绑定监听端口: 2.通过accept()方法监听客户端请求: 3.建立连接后通过输入流读取客户端发送的请求信息; 4.通过输出流向客户端发送响应信息; ...

  3. Autofac解耦事件总线

    事件总线之Autofac解耦 事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线 ...

  4. .Net 事件总线之Autofac解耦

    事件总线是通过一个中间服务,剥离了常规事件的发布与订阅(消费)强依赖关系的一种技术实现.事件总线的基础知识可参考圣杰的博客[事件总线知多少] 本片博客不再详细概述事件总线基础知识,核心点放置使用Aut ...

  5. Vue事件总线(eventBus)$on()会多次触发解决办法

    项目中使用了事件总线eventBus来进行两个组件间的通信, 使用方法是是建立eventBus.js文件,暴露一个空的Vue实例,如下: import Vue from 'vue'export def ...

  6. 【Shashlik.EventBus】.NET 事件总线,分布式事务最终一致性

    [Shashlik.EventBus].NET 事件总线,分布式事务最终一致性 简介 github https://github.com/dotnet-shashlik/shashlik.eventb ...

  7. 如何在 pyqt 中实现全局事件总线

    前言 在 Qt 中可以使用信号和槽机制很方便地实现部件之间的通信,考虑下面这样的场景: 我想要点击任意一个专辑卡并通知主界面跳转到专辑界面,那么一种实现方式如上图所示:点击任意一个蓝色方框所示的专辑卡 ...

  8. HttpClient_001_初步实现项目01的servlet,与项目02的servlet,之间数据访问

    HttpClient_001_初步实现项目01的servlet,与项目02的servlet,之间数据访问 代码下载地址: http://download.csdn.net/detail/poiuy19 ...

  9. 【bird-java】分布式服务间的事件总线EventBus

    什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...

随机推荐

  1. 硕盟SM-T54| TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞

    硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...

  2. Linux学习笔记--终端命令

    ~ 表示用户目录路径 ls   显示当前目录下的文件或目录 -l 列出文件纤细信息l(list) -a 列出当前目录下所有文件及目录, 包含隐藏的a(all) mkdir   创建目录 -p 创建目录 ...

  3. 完美数java

    完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数.它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身.如果一个数恰好等于它的因子之和,则称该数为&q ...

  4. 跨域分布式系统单点登录的实现(CAS单点登录)

    1. 概述 上一次我们聊了一下<使用Redis实现分布式会话>,原理就是使用 客户端Cookie + Redis 的方式来验证用户是否登录. 如果分布式系统中,只是对Tomcat做了负载均 ...

  5. 羽夏看Win系统内核——环境搭建

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  6. python中字典按键、值进行排序

    看到排序,就不禁想起python中的sort和sorted sort是列表中的方法,用于对列表进行排序(改变的是原列表,不返回新列表) 用法: list.sort(key=None,reverse=T ...

  7. 【Python学习】print语句

    一.print 可以向屏幕上输出信息,print 后面一个空格再加上''中间放入要输出的内容. 二.print可以用逗号分隔语句,但是每有一个逗号就会出来一个空格. 1 >>> pr ...

  8. scrapy各种持久化存储的奇淫技巧

    理论 磁盘文件: 基于终端指令 1)保证parse方法返回一个可迭代类型的对象(存储解析到的页面内容) 2)使用终端指令完成数据存储到指定磁盘文件中的操作,如:scrapy crawl 爬虫文件名称 ...

  9. Shell系列(39) - dirname

    dirname作用 dirname实际工作中常常是跟$0一起使用 用于获取当前运行脚本的绝对路径 这个命令要放在shell脚本中使用,在命令行使用意义不大 [yutao@master01 ~]$ di ...

  10. 常用的jquery 中一些js

    目录: 1.验证用户登录信息 2. 获取下拉框所选中的元素 3.  动态获取 id 和对应文本框的值  4. table 中 tr  的隐藏 5 . 更换图片  6. ajax  进行提交 7. 判断 ...