Azure Service Fabric内部服务通信

时间:2017-05-29 17:02:36

标签: c# azure queue azure-service-fabric service-fabric-stateful

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

以下不起作用(对于Listener服务,没有任何要出队的内容):

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);
    }
}

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

所以我的问题是:

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

显然我可以使用Azure Service Bus,但出于以下几个原因我无法做到:

  • 在我的实际场景中,我将有几个队列(变量号),因此需要按需创建服务总线队列(这不是快速操作)
  • 向另一个Azure服务添加依赖项(因此会增加整个系统的失败概率)
  • 费用更高
  • 更复杂的部署

3 个答案:

答案 0 :(得分:3)

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

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

另一方面,开箱即用:

使用多个ReliableQueues创建一个有状态服务,并使用stand remoting通信公开其他服务可以调用的方法,如:

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

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

关于文档,不是没有用很多单词说可靠队列与1个服务绑定,但这取决于你如何解释this

  

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

如果您为所有调用代码添加了错误处理重试模式,则在调用之间不需要排队,请参阅https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication

链接的相关部分在这里:

  

异常处理程序负责确定发生异常时要采取的操作。例外分为可重试和非可重试。   不可重试的异常只是重新回放给调用者。   可重试的异常进一步分为瞬态和非瞬态。   瞬态异常是可以在不重新解析服务端点地址的情况下简单地重试的异常。这些将包括瞬态网络问题或服务错误响应,而不是指示服务端点地址不存在的响应。   非瞬态异常是需要重新解析服务端点地址的异常。其中包括指示无法访问服务端点的异常,表示服务已移至其他节点。