3

我目前有一个由多个服务组成的 Service Fabric 应用程序。我想要实现的是一种排队机制,因此一个服务可以将消息发布到队列,而另一个服务可以从同一个队列接收消息

以下不起作用(对于侦听器服务,没有什么可出队的):

PublisherService

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    var myQueue = await StateManager.GetOrAddAsync<IReliableQueue<string>>("fooQueue");
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();
        using (var tx = this.StateManager.CreateTransaction())
        {
            // Put some message in the queue
            await myQueue.EnqueueAsync(tx, "Foobar");

            await tx.CommitAsync();
        }

        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
    }
}

ListenerService

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    var myQueue = await StateManager.GetOrAddAsync<IReliableQueue<string>>("fooQueue");
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();
        using (var tx = this.StateManager.CreateTransaction())
        {
            var result = await myQueue.TryDequeueAsync(tx);

            if (result.HasValue)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "New message receieved: {0}", result.Value.ToString());
            }

            await tx.CommitAsync();
        }

        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
    }
}

看起来队列的范围仅限于单个 Service。这似乎不是文档中指定的限制。

所以我的问题是:

  • 实际上是一些未记录的限制吗?
  • 还是上面的代码有问题?
  • 我怎样才能实现上述场景(一个服务将消息添加到队列中,另一个服务从同一个队列中检索消息)?

显然我可以使用 Azure 服务总线,但由于以下几个原因我不能:

  • 在我实际的真实场景中,我将有几个队列(可变数量),因此需要按需创建服务总线队列(这并不是一个快速操作)
  • 将依赖项添加到另一个 Azure 服务(因此增加了整个系统的故障概率)
  • 花费更多
  • 更复杂的部署
  • 等等
4

3 回答 3

3

ReliableQueues 是服务本地的,是的,因为它的目的是存储该特定服务的状态。该状态被复制到其他实例。这就像System.Collections.Generic.Queue<T>.Net 中的正常情况。

对于低成本解决方案,您可以使用Azure Storage Queues。是的,它增加了依赖,但它具有高可用性。这是一个权衡,只有您可以决定接受与否。

另一方面,跳出框框思考:

创建具有多个 ReliableQueue 的有状态服务,并公开其他服务可以使用标准远程通信调用的方法,例如:

class QueuingService
{
    void AddToQueue<T>(string queuename, T input) { .. }
    void DeQueue(string queuename) { .. }
}

这当然会产生依赖关系,但它具有 Service Fabric 提供的所有安全机制,并且不会花费您太多。但是话又说回来,您自己正在构建一个糟糕的人工服务总线/天蓝色存储队列。

关于文档,不,它并没有用很多词说明可靠队列与 1 个服务相关联,但这取决于您如何解释这一点

Service Fabric 通过 Reliable Collections 为 .NET 开发人员提供了一个有状态的编程模型。具体来说,Service Fabric 提供可靠的字典和可靠的队列类。当您使用这些类时,您的状态(我的解释:服务的状态)被分区(为了可伸缩性)、复制(为了可用性)和在一个分区内进行事务处理(为了 ACID 语义)。

于 2017-05-29T17:45:19.163 回答
1

查看为此目的而创建的Priority Queue Service 。

于 2017-05-30T13:41:51.693 回答
1

如果向所有调用代码添加故障处理重试模式,则调用之间不需要队列,请参阅https://docs.microsoft.com/en-us/azure/service-fabric/service-结构可靠的服务通信

链接中的相关部分在这里:

异常处理程序负责确定发生异常时要采取的操作。异常分为可重试和不可重试。不可重试的异常只是被重新抛出给调用者。可重试异常进一步分为瞬态和非瞬态。瞬态异常是那些可以简单地重试而无需重新解析服务端点地址的异常。这些将包括暂时的网络问题或服务错误响应,而不是那些表明服务端点地址不存在的问题。非瞬态异常是需要重新解析服务端点地址的异常。这些包括指示无法到达服务端点的异常,指示服务已移动到不同的节点。

于 2017-09-20T08:03:07.297 回答