【问题标题】:Injecting stateless service in Stateful service in service fabric在服务结构中的有状态服务中注入无状态服务
【发布时间】:2017-05-23 09:44:02
【问题描述】:

我有状态服务,可以处理可靠队列中的数据(在 while 循环内)。数据的处理实际上调用了无状态服务。

由于无状态服务可以从一个节点移动到另一个节点,我在有状态服务的构造函数中注入这种依赖项(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项没有固定到一个节点。

【问题讨论】:

    标签: azure-service-fabric service-fabric-stateful


    【解决方案1】:

    如果您使用remoting 与无状态服务通信,您可以在构造函数中注入IServiceProxyFactory。这样,您还可以注入 Mock 用于测试目的。

    这个答案后问题发生了变化。 附加信息:服务远程处理服务地址的解析、连接、重试和错误处理

    示例:

        public class MyStatefulService : StatefulService
        {
            private readonly Uri CalledServiceName = new Uri("fabric:/MyApp/MyStatefulService");
            private readonly IServiceProxyFactory ServiceProxyFactory;  
    
            public MyStatefulService(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica, IServiceProxyFactory serviceProxyFactory = null)
               : base(serviceContext, reliableStateManagerReplica)        
            {       
                ServiceProxyFactory = serviceProxyFactory ?? new ServiceProxyFactory();
            }
    
            public Task InsertAsync(object value)
            {
                var serviceProxy = ServiceProxyFactory.CreateServiceProxy<IMyStatefulService>(CalledServiceName);        
                return serviceProxy.InsertAsync(value);
            }
        }
    

    【讨论】:

    • 是的。我将其初始化/调用为:ServiceProxy.Create&lt;IMyStatelessService&gt;(serviceUri)
    • 是的,这就是我的出发点——注入依赖项以实现可测试性。无论如何,由于我在循环内调用无状态服务,我需要在可靠队列的每次迭代中初始化/发现该服务?或者使用相同的 serviceProxy 实例是否安全?这意味着如果该服务在节点中不再可用,SF 将处理发现。
    • 您可以安全地重复使用同一个 serviceproxy。当出现问题时,它会自动重试并重新发现新端点。
    • @LoekD 我知道注入 serviceproxyfactory,但是你能注入 serviceproxy 吗?在服务的生命周期内重用 serviceproxy 是否安全?
    【解决方案2】:

    TL;DR; 是的,您可以,大多数情况下服务远程客户端会为您处理这种情况。

    解释: 当您创建代理以使用服务远程处理与服务通信时,您将获得一个能够重试与实际服务通信的客户端。在文档 (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-and-communicate-with-services) 中有一些 描述,尤其是描述服务发现和解析的部分:

    解析和连接服务涉及循环运行以下步骤:

    • Resolve:获取服务已从命名服务发布的端点。
    • 连接:通过它在该端点上使用的任何协议连接到服务。
    • 重试:连接尝试可能由于多种原因而失败,例如,自上次解析端点地址后服务已移动。在这种情况下,需要重试前面的解析和连接步骤,并重复此循环,直到连接成功。

    最后一部分与您的问题非常相关,如果服务自上次以来已移动,它实际上会重试解决,然后连接。因此,这意味着如果您使用结构传输来远程访问您的服务,实际上有一个内置机制可以处理这种情况。

    当您调用IServiceProxyFactory (Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory) 的默认实现时,您将获得一个使用IServiceRemotingClient 进行通信的ServiceProxy。 在IServiceRemotingClient 的重试部分中,如果与已知结构错误相关,则与该IExceptionHandler 关联的瞬态和非瞬态错误都会重试。其中之一是服务的地址以某种方式发生了变化。

    有一个易于使用的静态 ServiceProxy 类(通过ServiceProxy.Create&lt;...&gt; 使用),这个实际上只在引擎盖下使用Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory。正如@LoekD 在他的回答中指出的那样,在构造函数中注入IServiceProxyFactory 实例的方法可以帮助您进行测试。在实时代码中注入Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory 的实例,并在测试中提供自己的模拟。在您的代码中,您使用它类似于静态ServiceProxy,例如_serviceProxyFactory.Create&lt;IMyService&gt;(...).

    注意,如果您在另一方面实现自己的IServiceRemotingClient,那么您需要考虑重试各种结构异常(例如FabricNotReadableExceptionFabricTransientException。查看https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-errors-and-exceptions 以获取有关常见异常的更多详细信息在 FabricClients 中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-04
      • 2018-07-25
      • 2016-12-04
      • 1970-01-01
      • 2016-11-07
      • 2014-07-04
      • 2020-02-29
      • 2011-02-05
      相关资源
      最近更新 更多