我有状态服务,处理可靠队列中的数据(在while循环内)。数据处理实际上称为无状态服务。
由于无状态服务可以从一个节点移动到另一个节点,因此在有状态服务的构造函数中注入此依赖关系(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项不能修复一个节点。
答案 0 :(得分:2)
如果您使用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);
}
}
答案 1 :(得分:0)
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.Create<...>
如果与已知结构错误相关,则会重试瞬态和非瞬态错误。其中一个原因是服务的地址以某种方式改变了。
有一个易于使用的静态ServiceProxy类(通过Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory
使用),这个类实际上只使用了IServiceProxyFactory
。正如@LoekD在他的回答中所指出的那样,在构造函数中注入Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory
实例的方法可以帮助您进行测试。在实时代码中,您注入ServiceProxy
的实例,并在测试中提供您自己的模拟。在您的代码中,您使用它类似于静态_serviceProxyFactory.Create<IMyService>(...)
,例如IServiceRemotingClient
。
注意,如果您另一方面实现自己的FabricNotReadableException
,则需要考虑重试各种结构异常(例如FabricTransientException
和{{1}}。请检查{{3有关FabricClients中常见异常的更多详细信息。