简介
Redis 是一个内存数据结构存储系统,常被用作消息代理、缓存或数据库。它支持[队列](https://redis.io/glossary/redis-queue/),你可以通过 Paramore.Brighter.MessagingGateway.Redis 包实现与 Redis 的集成。
要求
- .NET 8 或更高版本
- 包含以下 NuGet 包的 .NET 项目:
- Paramore.Brighter.MessagingGateway.Redis:启用 Redis 集成。
- Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection:将 Brighter 与 Microsoft DI 集成。
- Paramore.Brighter.ServiceActivator.Extensions.Hosting:将 Brighter 作为后台服务托管。
- Serilog.AspNetCore:结构化日志记录(可选但推荐)。
Brighter 回顾
在继续 Redis 配置之前,先回顾一下我们已知的 Brighter 核心概念。
请求(命令/事件)
通过 IRequest 定义消息:
public class Greeting() : Event(Guid.NewGuid())
{
public string Name { get; set; } = string.Empty;
}
- 命令:单接收者操作(例如 SendEmail)。
- 事件:广播通知(例如 OrderShipped)。
消息映射器
在 Brighter 消息与应用程序对象之间转换:
public class GreetingMapper : IAmAMessageMapper<Greeting>
{
public Message MapToMessage(Greeting request)
{
var header = new MessageHeader();
header.Id = request.Id;
header.TimeStamp = DateTime.UtcNow;
header.Topic = "greeting.topic"; // 目标主题
header.MessageType = MessageType.MT_EVENT;
var body = new MessageBody(JsonSerializer.Serialize(request));
return new Message(header, body);
}
public Greeting MapToRequest(Message message)
{
return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
}
}
请求处理器
处理传入消息:
public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
public override Greeting Handle(Greeting command)
{
logger.LogInformation("你好 {Name}", command.Name);
return base.Handle(command);
}
}
使用 Redis 配置 Brighter
1. 连接设置
定义 Redis 连接信息:
var connection = new RedisMessagingGatewayConfiguration
{
RedisConnectionString = "localhost:6379?connectTimeout=1000&sendTimeout=1000&",
MaxPoolSize = 10,
MessageTimeToLive = TimeSpan.FromMinutes(10)
};
2. Redis 订阅
订阅队列:
.AddServiceActivator(opt =>
{
opt.Subscriptions = [
new RedisSubscription<Greeting>(
new SubscriptionName("kafka.greeting.subscription"),
new ChannelName("greeting.queue"),
new RoutingKey("greeting.topic"),
makeChannels: OnMissingChannel.Create
),
];
opt.ChannelFactory = new ChannelFactory(
new RedisMessageConsumerFactory(connection)
);
})
3. Redis 生产者配置
发布事件到队列:
.UseExternalBus(new RedisProducerRegistryFactory(connection, [
new RedisMessagePublication
{
Topic = new RoutingKey("greeting.topic"),
MakeChannels = OnMissingChannel.Create
}
]).Create());
限制与注意事项
1. ServiceStack.Redis 授权限制
Brighter 的 Redis 集成依赖于 `ServiceStack.Redis.Core`,该库在未购买商业授权的情况下对并发消息消费有限制。这可能成为高吞吐量系统的瓶颈。
2. 当前不支持 Redis Streams
Brighter 目前使用 Redis 列表实现队列,而非更现代的 Redis Streams(后者支持持久化和流处理)。未来版本将新增 Redis Streams 支持以提升扩展性。
结论
将 Brighter 与 Redis 集成可在 .NET 应用程序中实现轻量级、可扩展的消息传递。通过利用 Redis 的内存速度和 Brighter 的抽象层,开发者可以快速构建高性能系统。
在生产环境中使用时,需根据 Brighter 的最新文档验证 Redis 配置,因为对 Redis Streams 和替代客户端的支持可能会更新。
参考
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Paramore.Brighter;
using Paramore.Brighter.Extensions.DependencyInjection;
using Paramore.Brighter.MessagingGateway.Redis;
using Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection;
using Paramore.Brighter.ServiceActivator.Extensions.Hosting;
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
var host = new HostBuilder()
.UseSerilog()
.ConfigureServices(
(_, services) =>
{
var connection = new RedisMessagingGatewayConfiguration
{
RedisConnectionString = "localhost:6379?connectTimeout=1000&sendTimeout=1000&",
MaxPoolSize = 10,
MessageTimeToLive = TimeSpan.FromMinutes(10)
};
services
.AddHostedService<ServiceActivatorHostedService>()
.AddServiceActivator(opt =>
{
opt.Subscriptions =
[
new RedisSubscription<Greeting>(
new SubscriptionName("kafka.greeting.subscription"),
new ChannelName("greeting.topic"),
new RoutingKey("greeting.topic"),
makeChannels: OnMissingChannel.Create
),
];
opt.ChannelFactory = new ChannelFactory(
new RedisMessageConsumerFactory(connection)
);
})
.AutoFromAssemblies()
.UseExternalBus(
new RedisProducerRegistryFactory(
connection,
[
new RedisMessagePublication
{
MakeChannels = OnMissingChannel.Create,
Topic = new RoutingKey("greeting.topic"),
},
]
).Create()
);
}
)
.Build();
await host.StartAsync();
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(10));
Console.Write("Say your name (or q to quit): ");
var name = Console.ReadLine();
if (string.IsNullOrEmpty(name))
{
continue;
}
if (name == "q")
{
break;
}
var process = host.Services.GetRequiredService<IAmACommandProcessor>();
process.Post(new Greeting { Name = name });
}
await host.StopAsync();
public class Greeting() : Event(Guid.NewGuid())
{
public string Name { get; set; } = string.Empty;
}
public class GreetingMapper : IAmAMessageMapper<Greeting>
{
public Message MapToMessage(Greeting request)
{
var header = new MessageHeader();
header.Id = request.Id;
header.TimeStamp = DateTime.UtcNow;
header.Topic = "greeting.topic";
header.MessageType = MessageType.MT_EVENT;
var body = new MessageBody(JsonSerializer.Serialize(request));
return new Message(header, body);
}
public Greeting MapToRequest(Message message)
{
return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
}
}
public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
public override Greeting Handle(Greeting command)
{
logger.LogInformation("Hello {Name}", command.Name);
return base.Handle(command);
}
}
1029

被折叠的 条评论
为什么被折叠?



