【发布时间】:2017-05-23 09:44:02
【问题描述】:
我有状态服务,可以处理可靠队列中的数据(在 while 循环内)。数据的处理实际上调用了无状态服务。
由于无状态服务可以从一个节点移动到另一个节点,我在有状态服务的构造函数中注入这种依赖项(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项没有固定到一个节点。
【问题讨论】:
标签: azure-service-fabric service-fabric-stateful
我有状态服务,可以处理可靠队列中的数据(在 while 循环内)。数据的处理实际上调用了无状态服务。
由于无状态服务可以从一个节点移动到另一个节点,我在有状态服务的构造函数中注入这种依赖项(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项没有固定到一个节点。
【问题讨论】:
标签: azure-service-fabric service-fabric-stateful
如果您使用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<IMyStatelessService>(serviceUri)
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<...> 使用),这个实际上只在引擎盖下使用Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory。正如@LoekD 在他的回答中指出的那样,在构造函数中注入IServiceProxyFactory 实例的方法可以帮助您进行测试。在实时代码中注入Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory 的实例,并在测试中提供自己的模拟。在您的代码中,您使用它类似于静态ServiceProxy,例如_serviceProxyFactory.Create<IMyService>(...).
注意,如果您在另一方面实现自己的IServiceRemotingClient,那么您需要考虑重试各种结构异常(例如FabricNotReadableException 和FabricTransientException。查看https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-errors-and-exceptions 以获取有关常见异常的更多详细信息在 FabricClients 中。
【讨论】: