首页 > 解决方案 > ServiceStack.Redis:PooledRedisClientManager 和 RedisManagerPool 等待 prev req 完成

问题描述

我正在测试这里显示的 Redis“全双工”通信,并阅读文档,我认为PooledRedisClientManager还有RedisManagerPool一个客户端池,因此能够并行处理多个 MQ 消息。

但是,在Github 上的测试项目中,在我看来情况并非如此,或者我遗漏了一些东西。解决方案包括:

我在 HelloService 中添加了一个 Thread.Sleep Any(Hello req),当我从 EventPublisher 快速发送几个 Hello DTO 时,我期望它们在 EventConsumer 中同时处理,因为我认为将使用客户端池。然而,情况似乎并非如此。

s 一个接一个地处理,HelloResponse似乎在同一个线程上。请看这个简短的视频:

http://somup.com/cYheY8iNml

在这里,我连续快速地向 MQ 发出了三个 Hello DTO,在 VS 的输出窗口中,您可以看到三个 DTO 是一个接一个地处理的。

我没有找到可以指定池大小的PooledRedisClientManager设置RedisManagerPool

标签: c#redisservicestackservicestack.redis

解决方案


我认为 PooledRedisClientManager 和 RedisManagerPool 有一个客户端池

这个说法是真的。

从而能够并行处理多个 MQ 消息。

这是一个无效的结论,没有上下文就毫无意义。池化Redis 客户端管理器自己不执行任何操作,即它们只管理一个 redis 客户端池,这意味着从池中检索客户端时:

var redis = clientsManager.GetClient();

RedisClient即单个 TCP 连接的客户端到 redis 服务器)是从客户端管理器管理的客户端池中检索的,并且当客户端被释放时,它会返回到池中,而不是终止 TCP 连接。

这就是当某物使用池时可以假设的所有内容,客户端管理器不自己执行 Redis 命令,并且使用它的应用程序做什么是特定于它们的实现的。他们使用池的事实是无关紧要的,他们可以很容易地配置为使用没有使用池的BasicRedisClientManager,即应用程序对客户端管理器的使用不会对它的使用方式做出任何假设。

在您的示例项目中,您使用Redis MQ来执行您的 ServiceStack 服务:

mqHost.RegisterHandler<Hello>(base.ExecuteMessage);
mqHost.Start(); //Starts listening for messages

在您之前的回答中,您引用了:

创建一个 Redis MQ 服务器,它在自己的后台线程上处理每条消息。

完整的评论继续提供一个例子:

i.e. if you register 3 handlers it will create 7 background threads:
///   - 1 listening to the Redis MQ Subscription, getting notified of each new message
///   - 3x1 Normal InQ for each message handler
///   - 3x1 PriorityQ for each message handler (Turn off with DisablePriorityQueues)

这解释了 Redis MQ 服务器如何处理消息,即每个消息类型在其自己的后台线程上处理,因此如果您阻止消息工作线程,那么您将阻止线程以阻止该类型的其他消息(即请求 DTO)。

mqHost.RegisterHandler<Hello>(base.ExecuteMessage);

它不会阻止在它们自己的后台线程或优先级 MQ 线程上处理的其他消息,该类型处理使用Priority>0.

Redis MQ文档提供了一个示例,说明如何通过noOfThreads在注册处理程序时指定 来增加用于处理每种消息类型的线程数:

轻松并行化和成倍增加您的服务吞吐量

RedisMqServer 还支持为单个请求生成任意数量的后台线程,因此如果发布到 twitter 是一个 IO 密集型操作,您可以通过简单地分配 2 个或更多工作线程来使吞吐量翻倍,例如:

mqService.RegisterHandler<PostStatusTwitter>(ExecuteMessage, noOfThreads:2);
mqService.RegisterHandler<CallFacebook>(ExecuteMessage);
mqService.RegisterHandler<EmailMessage>(ExecuteMessage);

推荐阅读