我在Windows服务中使用RabbitMQ .net客户端。我有大量的邮件批量发送然后被处理,然后输出放在另一个队列上。我正在创建心跳为30的连接工厂,然后在连接或订户丢失时创建连接。在生产中,我的代码可能在大多数情况下都有效。但是,在我的集成测试中,我知道它在大多数情况下失败了。这是我的代码:
public void ReceiveAll(Func<IDictionary<ulong, byte[]>, IOnStreamWatchResult> onReceiveAllCallback, int batchSize, CancellationToken cancellationToken)
{
IModel channel = null;
Subscription subscription = null;
while (!cancellationToken.IsCancellationRequested)
{
if (subscription == null || subscription.Model.IsClosed)
{
channel = _channelFactory.CreateChannel(ref _connection, _messageQueueConfig, _connectionFactory);
// This instructs the channel to not prefetch more than batch count into shared queue
channel.BasicQos(0, Convert.ToUInt16(batchSize), false);
subscription = new Subscription(channel, _messageQueueConfig.Queue, false);
}
try
{
BasicDeliverEventArgs message;
var dequeuedMessages = new Dictionary<ulong, byte[]>();
do
{
if (subscription.Next(_messageQueueConfig.DequeueTimeout.Milliseconds, out message))
{
if (message == null)
{
// This means channel is closed and the messages in shared queue would get moved back to ready state
DisposeChannelAndSubcription(ref channel, ref subscription);
ReceiveAll(onReceiveAllCallback, batchSize, cancellationToken);
}
else
{
dequeuedMessages.Add(message.DeliveryTag, message.Body);
}
}
} while (message != null && batchSize > dequeuedMessages.Count && !cancellationToken.IsCancellationRequested);
if (cancellationToken.IsCancellationRequested)
{
if (dequeuedMessages.Any())
{
NackUnProcessedMessages(subscription, dequeuedMessages.Keys);
}
DisposeChannelAndSubcription(ref channel, ref subscription);
dequeuedMessages.Clear();
break;
}
try
{
var onStreamWatchResult = onReceiveAllCallback(dequeuedMessages);
AckProcessedMessages(subscription, onStreamWatchResult.Processed);
NackUnProcessedMessages(subscription, onStreamWatchResult.UnProcessed);
dequeuedMessages.Clear();
}
catch(Exception unhandledException)
{
NackUnProcessedMessages(subscription, dequeuedMessages.Keys);
}
}
catch (EndOfStreamException endOfStreamException)
{
DisposeChannelAndSubcription(ref channel, ref subscription);
}
catch (OperationInterruptedException operationInterruptedException)
{
DisposeChannelAndSubcription(ref channel, ref subscription);
}
}
}
批量大小设置为4,因为我在集成测试中放了4条消息,这只是我在运行单元测试后运行的一个Windows服务。
这里的问题是,几乎总是,订阅者预取4条消息,如预期的那样,对前两个迭代返回true。但是之后它返回false。我相信这种情况正在发生,因为我的消息没有得到正确的解决。在我的集成测试中,我确认2和nack 2消息,然后再次读取2个nacked消息以清除队列。但是,在nacking之后,消息不会返回就绪状态,因此测试会挂起。我在这做错了什么?我不理解nacking文档中的某些内容吗?这是我的代码:
subscription.Model.BasicNack(deliveryTag, false, true);