在 MassTransit 中,Command(命令) 和Event(事件) 的核心区别在于意图(Intention) 和传递方式(Delivery)。简单来说:
-
Command(命令) :是告诉一个服务去做什么 。它使用
Send发送到特定 的端点,期望只有一个消费者处理它。 -
Event(事件) :是宣告某件事情已经发生 。它使用
Publish进行广播,所有订阅了该事件的服务都会收到一份副本
| 维度 | Command (命令) | Event (事件) |
|---|---|---|
| 核心意图 | 指示、请求执行一个动作 | 通知、宣告一个已发生的事实 |
| 目标消费者 | 单一 消费者,由一个服务实例处理 | 零到多个消费者,所有订阅者都会收到 |
| 传递方式 | 使用 Send 发送到已知的特定队列/端点 |
使用 Publish 进行广播/发布-订阅 |
| 命名规范 | 动词-名词 ,如 SubmitOrder |
名词-动词(过去时) ,如 OrderSubmitted |
| 紧耦合/松耦合 | 发送方知道接收方的确切地址,耦合度更高 | 发送方无需知道接收方,实现松耦合 |
然后定义一个web程序
引用的nuget包
XML
<ItemGroup>
<PackageReference Include="MassTransit.RabbitMQ" Version="8.5.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.2" />
</ItemGroup>
cs
using MassTransit;
using WebApplication_MT.Customers;
using WebApplication_MT.Endpoints;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// 添加 Swagger 服务
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddMassTransit(t =>
{
t.AddConsumer<OrderCreatedWebConsumer>();
t.AddConsumer<TestCommandWebConsumer>();
//使用内存传输(适合开发和测试环境)
//t.UsingInMemory((context, cfg) =>
//{
// // 强烈建议加上这行,让 MassTransit 自动配置队列和消费者绑定
// cfg.ConfigureEndpoints(context);
//});
//使用 RabbitMQ 传输/可以跨程序传输消息(适合生产环境)
t.UsingRabbitMq((contex, cfg) =>
{
cfg.Host("localhost", "/", h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ConfigureEndpoints(contex);
});
});
//配置日志
builder.Services.AddLogging(ser =>
{
ser.AddConsole();
ser.SetMinimumLevel(LogLevel.Debug);
});
var app = builder.Build();
// Configure the HTTP request pipeline.
// 配置 Swagger 中间件
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//app.MapWeatherEndpoint();
app.MapMTEndpoint();
app.Run();
api定义
cs
using ClassLibrary_MT.MessageCommands;
using ClassLibrary_MT.MessageContracts;
using ClassLibrary_MT.MessageEvents;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using WebApplication_MT.Customers;
namespace WebApplication_MT.Endpoints;
public static class MTEndpoint
{
public static void MapMTEndpoint(this IEndpointRouteBuilder app)
{
app.MapPost("/massTransit/event", async ([FromBody] OrderCreateEvent info, IPublishEndpoint publish, ILogger<OrderCreateEvent> logger) =>
{
logger.LogInformation($"api收到请求(Event):{info}");
await publish.Publish(info);
});
app.MapPost("/massTransit/command/self", async ([FromBody] TestCommand info, ISendEndpointProvider sendEndpointProvider, ILogger<OrderCreateEvent> logger) =>
{
logger.LogInformation($"api收到请求(Command):{info}");
// 发送到特定队列
var endpoint = await sendEndpointProvider.GetSendEndpoint(
new Uri($"queue:TestCommandWeb"));
await endpoint.Send(info);
});
app.MapPost("/massTransit/command/other", async ([FromBody] TestCommand info, ISendEndpointProvider sendEndpointProvider, ILogger<OrderCreateEvent> logger) =>
{
logger.LogInformation($"api收到请求(Command):{info}");
// 发送到特定队列
var endpoint = await sendEndpointProvider.GetSendEndpoint(
new Uri($"queue:TestCommand"));
await endpoint.Send(info);
});
app.MapPost("/massTransit/request", async ([FromBody] OrderRequest request, IRequestClient<OrderRequest> client, ILogger<OrderCreateEvent> logger) =>
{
logger.LogInformation($"api收到(request):{request}");
// 关键:发送请求并等待响应(超时时间5秒)
var response = await client.GetResponse<OrderResponse>(request, timeout: RequestTimeout.After(s: 5));
var result = response.Message;
logger.LogInformation($"api收到(response):{result}");
return Results.Ok(result);
});
}
}
定义一些 Consumer
cs
using ClassLibrary_MT.MessageCommands;
using ClassLibrary_MT.MessageEvents;
using MassTransit;
namespace WebApplication_MT.Customers;
public class OrderCreatedWebConsumer : IConsumer<OrderCreateEvent>
{
private readonly ILogger<OrderCreatedWebConsumer> _logger;
public OrderCreatedWebConsumer(ILogger<OrderCreatedWebConsumer> logger)
{
_logger = logger;
}
public Task Consume(ConsumeContext<OrderCreateEvent> context)
{
_logger.LogInformation($"web收到订单事件: {context.Message}");
return Task.CompletedTask;
}
}
cs
using ClassLibrary_MT.MessageCommands;
using MassTransit;
namespace WebApplication_MT.Customers
{
public class TestCommandWebConsumer : IConsumer<TestCommand>
{
private readonly ILogger<TestCommandWebConsumer> _logger;
public TestCommandWebConsumer(ILogger<TestCommandWebConsumer> logger)
{
_logger = logger;
}
public Task Consume(ConsumeContext<TestCommand> context)
{
_logger.LogInformation($"web收到订单命令: {context.Message}");
return Task.CompletedTask;
}
}
}
然后运行在swaager 页面触发,能到Consumer