.NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 详解)--学习笔记
2.6.7 RabbitMQ -- Masstransit 详解
- Consumer 消费者
- Producer 生产者
- Request-Response 请求-响应
Consumer 消费者
在 MassTransit 中,一个消费者可以消费一种或多种消息
消费者的类型包括:普通消费者,saga,saga 状态机,路由活动(分布式追踪),处理器 handlers,工作消费者 job comsumers
- Consumer
- Instance
- Handler
- Others
Consumer
public class Program
{
public static async Task Main()
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.ReceiveEndpoint("order-service", e =>
{
e.Consumer<SubmitOrderConsumer>();
});
});
}
}
继承 IConsumer,实现 Consume 方法
class SubmitOrderConsumer :
IConsumer<SubmitOrder>
{
public async Task Consume(ConsumeContext<SubmitOrder> context)
{
await context.Publish<OrderSubmitted>(new
{
context.Message.OrderId
});
}
}
三个原则:
- 拥抱 The Hollywood Principle, which states, "Dont't call us, we'll call you."
- Consume 方法是一个被等待的方法,在执行中时其他消费者无法接收到这个消息,当这个方法完成的时候,消息被 ack,并且从队列中移除
- Task 方法异常会导致消息触发 retry,如果没有配置重试,消息将被投递到失败队列
Instance
public class Program
{
public static async Task Main()
{
var submitOrderConsumer = new SubmitOrderConsumer();
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.ReceiveEndpoint("order-service", e =>
{
e.Instance(submitOrderConsumer);
});
});
}
}
所有接收到的消息都由一个消费者来实例来处理(请确保这个消费者类是线程安全)
Consumer 每次接收到消息都会 new 一个实例
Handler
public class Program
{
public static async Task Main()
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.ReceiveEndpoint("order-service", e =>
{
e.Handler<SubmitOrder>(async context =>
{
await Console.Out.WriteLineAsync($"Submit Order Received: {context.Message.OrderId}");
});
});
});
}
}
通过一个委托 Lambda 方法,来消费消息
Others
- Saga<>
- StateMachineSaga<>
Producer 生产者
消息的生产可以通过两种方式产生:发送和发布
发送的时候需要指定一个具体的地址 DestinationAddress,发布的时候消息会被广播给所有订阅了这个消息类型的消费者
基于这两种规则,消息被定义为:命令 command 和事件 event
- send
- publish
send
可以调用以下对象的 send 方法来发送 command:
- ConsumeContext (在 Consumer 的 Consumer 方法参数中传递)
- ISendEndpointProvider(可以从 DI 中获取)
- IBusControl(最顶层的控制对象,用来启动和停止 masstransit 的控制器)
ConsumeContext
public class SubmitOrderConsumer :
IConsumer<SubmitOrder>
{
private readonly IOrderSubmitter _orderSubmitter;
public SubmitOrderConsumer(IOrderSubmitter submitter)
=> _orderSubmitter = submitter;
public async Task Consume(IConsumeContext<SubmitOrder> context)
{
await _orderSubmitter.Process(context.Message);
await context.Send(new StartDelivery(context.Message.OrderId, DateTime.UtcNow));
}
}
ISendEndpointProvider
public async Task SendOrder(ISendEndpointProvider sendEndpointProvider)
{
var endpoint = await sendEndpointProvider.GetSendEndpoint(_serviceAddress);
await endpoint.Send(new SubmitOrder { OrderId = "123" });
}
publish
- 发送地址
- 短地址
- Convention Map
发送地址
- rabbitmq://localhost/input-queue
- rabbitmq://localhost/input-queue?durable=false
短地址
- GetSendEndpoint(new Uri("queue:input-queue"))
Convention Map
在配置文件中指定 map 规则
EndpointConvention.Map<StartDelivery>(new Uri(ConfigurationManager.AppSettings["deliveryServiceQueue"]));
直接发送
public class SubmitOrderConsumer :
IConsumer<SubmitOrder>
{
private readonly IOrderSubmitter _orderSubmitter;
public SubmitOrderConsumer(IOrderSubmitter submitter)
=> _orderSubmitter = submitter;
public async Task Consume(IConsumeContext<SubmitOrder> context)
{
await _orderSubmitter.Process(context.Message);
await context.Send(new StartDelivery(context.Message.OrderId, DateTime.UtcNow));
}
}
可以调用以下对象的 publish 方法来发送 event:
- ConsumeContext (在 Consumer 的 Consumer 方法参数中传递)
- IPublishEndpoint(可以从 DI 中获取)
- IBusControl(最顶层的控制对象,用来启动和停止 masstransit 的控制器)
IPublishEndpoint
public async Task NotifyOrderSubmitted(IPublishEndpoint publishEndpoint)
{
await publishEndpoint.Publish<OrderSubmitted>(new
{
OrderId = "27",
OrderDate = DateTime.UtcNow,
});
}
Request-Response 请求-响应
Request-Response 模式让应用程序之间解耦之后,依然采用同步的方式
- Consumer
- IClientFactory
- IRequestClient
- Send a request
Consumer
public async Task Consume(ConsumeContext<CheckOrderStatus> context)
{
var order = await _orderRepository.Get(context.Message.OrderId);
if (order == null)
throw new InvalidOperationException("Order not found");
await context.RespondAsync<OrderStatusResult>(new
{
OrderId = order.Id,
order.Timestamp,
order.StatusCode,
order.StatusText
});
}
需要处理返回类型 OrderStatusResult,异步方式模拟同步,实际上同样有消息队列,消费者处理过程
IClientFactory
public interface IClientFactory
{
IRequestClient<T> CreateRequestClient<T>(ConsumeContext context, Uri destinationAddress, RequestTimeout timeout);
IRequestClient<T> CreateRequestClient<T>(Uri destinationAddress, RequestTimeout timeout);
RequestHandle<T> CreateRequest<T>(T request, Uri destinationAddress, CancellationToken cancellationToken, RequestTimeout timeout);
RequestHandle<T> CreateRequest<T>(ConsumeContext context, T request, Uri destinationAddress, CancellationToken cancellationToken, RequestTimeout timeout);
}
通过 IBusControl 的 CreateClientFactory 方法可以得到 ClientFactory
IRequestClient
public interface IRequestClient<TRequest>
where TRequest : class
{
RequestHandle<TRequest> Create(TRequest request, CancellationToken cancellationToken, RequestTimeout timeout);
Task<Response<T>> GetResponse<T>(TRequest request, CancellationToken cancellationToken, RequestTimeout timeout);
}
RequestClient 可以创建请求,或者直接获得响应
Send a request
var serviceAddress = new Uri("rabbitmq://localhost/check-order-status");
var client = bus.CreateRequestClient<CheckOrderStatus>(serviceAddress);
var response = await client.GetResponse<OrderStatusResult>(new { OrderId = id});
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 详解)--学习笔记的更多相关文章
- .NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 介绍)--学习笔记
2.6.6 RabbitMQ -- Masstransit 介绍 Masstransit 是什么 Quickstart 消息 Message Masstransit 是什么 Masstransit 是 ...
- .NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 异常处理)--学习笔记
2.6.8 RabbitMQ -- Masstransit 异常处理 异常处理 其他 高级功能 异常处理 异常与重试 重试配置 重试条件 重新投递信息 信箱 异常与重试 Exception publi ...
- .NET 云原生架构师训练营(权限系统 代码实现 Store.EntityFramework)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...
- .NET 云原生架构师训练营(建立系统观)--学习笔记
目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...
- .NET 云原生架构师训练营(权限系统 RGCA 架构设计)--学习笔记
目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...
- .NET 云原生架构师训练营(模块二 基础巩固 敏捷开发)--学习笔记
2.7.1 敏捷开发 敏捷介绍 敏捷的起源 敏捷软件开发宣言 敏捷开发十二原则 生命周期对比 敏捷开发的特点 敏捷的发展 敏捷的核心 敏捷的起源 2001年,17个老头子在一起一边滑雪,一边讨论工作, ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 介绍和基础)--学习笔记
2.5.1 MongoDB -- 介绍 mysql vs mongo 快速开始 mysql vs mongo 对比 mysql mongo 数据存储 table 二维表结构,需要预先定义结构 json ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
2.5.6 MongoDB -- 问答系统 MongoDB 数据库设计 API 实现概述 MongoDB 数据库设计 设计优化 内嵌(mongo)还是引用(mysql) 数据一致性 范式:将数据分散到 ...
随机推荐
- 博客中css样式的正确设置
一.简介 博客园的文章是支持html代码和css样式的,即使是markdown写作.当某个标签需要特制样式时,我们可以自定义样式来覆盖掉原本的样式. 二.css样式优先级 参考至>>菜鸟教 ...
- java8+ Lambda表达式基本用法
LIST public class LambdaTest { @Getter @Setter @AllArgsConstructor static class Student{ private Lon ...
- 【科技】位运算(bitset)优化最长公共子序列算法
最长公共子序列(LCS)问题 你有两个字符串 \(A,B\),字符集为 \(\Sigma\),求 \(A, B\) 的最长公共子序列. 简单动态规划 首先有一个广为人知的 dp:\(f_{i,j}\) ...
- sql语句执行次序
from→on→join→where→group by→having→select→distinct→order by→limit
- linux 上安装部署python
一般在linux中使用python 需要安装pyenv 进行版本控制 因为linux6.9自带的Python是2.6的 同时很多命令都是基于2.6开发的 所以系统环境不能改 我们要开发 只能用pyen ...
- STL——容器(List)List 的数据元素插入和删除操作
push_back(elem); //在容器尾部加入一个元素 1 #include <iostream> 2 #include <list> 3 4 using namespa ...
- mysql全备、增量备份脚本
1.mysql全量备份及定时删除备份文件脚本 #!/bin/bash v_user="root" v_password="mysql" backup_date ...
- Spring自带的定时任务框架Schedule的优缺点及使用
spring自带的定时任务框架的有点:简单,拆箱即用 spring自带的定时任务框架的缺点: 不支持集群:为避免重复执行的问题 不支持生命周期统一管理:不重启服务情况下关闭,启动任务 不支持分片任务: ...
- css进阶 05-CSS的一些小知识
05-CSS的一些小知识 #隐藏盒子的几种方式 隐藏盒子,有以下几种方式: (1)方式一: overflow:hidden; //隐藏盒子超出的部分 (2)方式二: display: none; ...
- Ubuntu16.04网卡配置
新安装的Ubuntu16.04系统容易出现无法连接有线网络的问题,主要是因为网卡配置不完善,下面通过实操讲解如何解决该问题. 1. 查看网络设备 ifconfig 发现只有enp2s0和lo,没有et ...