分区队列

时间:2017-02-20 15:32:33

标签: azure azureservicebus azure-servicebus-queues

我遇到了IMessageSessionAsyncHandlerFactory的问题,当写入量达到0然后达到正常水平时,不会创建IMessageSessionAsyncHandler的新实例。

更准确地说,我SessionHandlerOptions使用值为500的MaxConcurrentSessionsprivate 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的策略,禁止在一段时间不活动后重新分配相同的会话?

编辑1: 我添加了两张图片来说明行为: enter image description here

当编写器停止并重新启动时,正在运行的阅读器无法像以前那样阅读。

在那一刻之后创建的会话数量也比以前低得多: enter image description here

1 个答案:

答案 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示例,你可以参考它。