【问题标题】:Azure Service Fabric inter service communicationAzure Service Fabric 服务间通信
【发布时间】:2017-10-30 01:18:00
【问题描述】:

我目前有一个由多个服务组成的 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 服务总线,但由于以下几个原因我不能:

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

【问题讨论】:

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


    【解决方案1】:

    ReliableQueues 是服务本地的,是的,因为它的目的是存储该特定服务的状态。该状态被复制到其他实例。它就像.Net 中的普通System.Collections.Generic.Queue&lt;T&gt;

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

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

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

    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 语义)。

    【讨论】:

    • 感谢您的回答,这是有道理的。我还不确定我会选择哪种方式(Azure 存储队列或远程通信)。每个都有自己的优点/缺点。再次感谢,这很有帮助。
    • 但话又说回来,您自己正在构建一个糟糕的人工服务总线/天蓝色存储队列。 - 这意味着这不是使用 ReliableQueue 的正确方法吗?
    • @AsValeO “正确的方式”是什么意思。如果您将它用于它的设计用途:将数据存储在它使用的位置,即在单个有状态服务内。你只是不能把它变成别的东西,比如跨越多个服务的队列。
    • 我们可以在本地使用像 azure 存储队列这样的东西吗?我们需要某种类型的事件驱动/本地解决方案,其中一个服务将触发一条消息,并将其存储在某个队列中,另一个服务将其从队列中弹出并处理它
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2020-10-24
        • 2016-09-29
        • 2019-06-21
        • 2017-12-29
        • 2020-12-29
        • 1970-01-01
        • 2018-09-06
        • 2021-03-01
        • 2017-06-09
        相关资源
        最近更新 更多