我遇到了IMessageSessionAsyncHandlerFactory
的问题,当写入量达到0然后达到正常水平时,不会创建IMessageSessionAsyncHandler
的新实例。
更准确地说,我SessionHandlerOptions
使用值为500的MaxConcurrentSessions
。private void RegisterHandler()
{
var sessionHandlerOptions = new SessionHandlerOptions
{
AutoRenewTimeout = TimeSpan.FromMinutes(1),
MessageWaitTimeout = TimeSpan.FromSeconds(1),
MaxConcurrentSessions = 500
};
_queueClient.RegisterSessionHandlerFactoryAsync(new SessionHandlerFactory(_callback), sessionHandlerOptions);
}
。这允许以超过1k msg / s的速度读取。
我读取的队列是分区队列。
队列中的消息量相当不变,但有时会降低到0.当卷恢复到正常水平时,SessionFactory不会产生任何处理程序,因此我无法读取消息了。就像会议没有被正确回收或者被持续等待一样。
以下是工厂注册的代码:
public class SessionHandlerFactory : IMessageSessionAsyncHandlerFactory
{
private readonly Action<BrokeredMessage> _callback;
public SessionHandlerFactory(Action<BrokeredMessage> callback)
{
_callback = callback;
}
public IMessageSessionAsyncHandler CreateInstance(MessageSession session, BrokeredMessage message)
{
return new SessionHandler(session.SessionId, _callback);
}
public void DisposeInstance(IMessageSessionAsyncHandler handler)
{
var disposable = handler as IDisposable;
disposable?.Dispose();
}
}
工厂类:
public class SessionHandler : MessageSessionAsyncHandler
{
private readonly Action<BrokeredMessage> _callback;
public SessionHandler(string sessionId, Action<BrokeredMessage> callback)
{
SessionId = sessionId;
_callback = callback;
}
public string SessionId { get; }
protected override async Task OnMessageAsync(MessageSession session, BrokeredMessage message)
{
try
{
_callback(message);
}
catch (Exception ex)
{
Logger.Error(...);
}
}
处理程序:
Dim myClass(5) as class1
Dim i as integer
For i = 0 to 5
set myClass(i) = New class
myClass(i).myProperty = "SomeValue"
Next i
我可以看到会话处理程序已关闭,并且在写入/读取处于正常级别时处理工厂。但是,一旦队列清空,就无法创建新的会话处理程序。是否存在分配会话ID的策略,禁止在一段时间不活动后重新分配相同的会话?
当编写器停止并重新启动时,正在运行的阅读器无法像以前那样阅读。
答案 0 :(得分:0)
队列中的消息量相当稳定,但有时会降低到0.当卷恢复到正常水平时,SessionFactory不会产生任何处理程序,所以我不能再看一遍消息。就像会议没有被正确回收或者被持续等待一样。
使用IMessageSessionHandlerFactory
控制IMessageSessionAsyncHandler
实例的创建方式时,您可以尝试记录所有IMessageSessionAsyncHandler
个实例的创建和销毁。
根据你的代码,我为这个问题创建了一个控制台应用程序。这是我的代码片段,用于初始化队列客户端和处理消息:
<强> InitializeReceiver 强>
static void InitializeReceiver(string connectionString, string queuePath)
{
_queueClient = QueueClient.CreateFromConnectionString(connectionString, queuePath, ReceiveMode.PeekLock);
var sessionHandlerOptions = new SessionHandlerOptions
{
AutoRenewTimeout = TimeSpan.FromMinutes(1),
MessageWaitTimeout = TimeSpan.FromSeconds(5),
MaxConcurrentSessions = 500
};
_queueClient.RegisterSessionHandlerFactoryAsync(new SessionHandlerFactory(OnMessageHandler), sessionHandlerOptions);
}
<强> OnMessageHandler 强>
static void OnMessageHandler(BrokeredMessage message)
{
var body = message.GetBody<Stream>();
dynamic recipeStep = JsonConvert.DeserializeObject(new StreamReader(body, true).ReadToEnd());
lock (Console.Out)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(
"Message received: \n\tSessionId = {0}, \n\tMessageId = {1}, \n\tSequenceNumber = {2}," +
"\n\tContent: [ title = {3} ]",
message.SessionId,
message.MessageId,
message.SequenceNumber,
recipeStep.title);
Console.ResetColor();
}
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
message.Complete();
}
根据我的测试,当队列中的消息量从正常到零以及从零到正常一段时间时,SessionHandler
可以按预期工作,如下所示:
我还尝试利用QueueClient.RegisterSessionHandlerAsync来测试这个问题,它也可以运行。另外,我发现了这个关于Service Bus Sessions的git示例,你可以参考它。