我有状态服务,可以处理可靠队列中的数据(在一个while循环内)。数据的处理实际上调用了无状态服务。
由于无状态服务可以从一个节点移动到另一个节点,我在有状态服务的构造函数中注入这种依赖项(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项没有固定到一个节点。
我有状态服务,可以处理可靠队列中的数据(在一个while循环内)。数据的处理实际上调用了无状态服务。
由于无状态服务可以从一个节点移动到另一个节点,我在有状态服务的构造函数中注入这种依赖项(无状态服务)是否安全?只是想确保在构造函数中初始化/注入的依赖项没有固定到一个节点。
如果您使用远程处理与无状态服务进行通信,则可以在构造函数中注入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);
}
}
TL;博士; 是的,您可以,在大多数情况下,远程服务客户端会为您处理这种情况。
解释:当您创建代理以使用远程服务与服务通信时,您将获得一个能够重试与实际服务通信的客户端。文档中有一些关于此的描述(https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-and-communicate-with-services),尤其是描述的部分服务发现和解决:
解析和连接服务涉及循环运行的以下步骤:
- Resolve:从命名服务获取服务已发布的端点。
- Connect:通过它在该端点上使用的任何协议连接到服务。
- 重试:连接尝试可能由于多种原因而失败,例如,如果自上次解析端点地址后服务已移动。在这种情况下,需要重试前面的解析和连接步骤,并重复此循环,直到连接成功。
最后一部分与您的问题非常相关,如果服务自上次以来已经移动,它实际上会重试解决,然后连接。因此,这意味着如果您使用结构传输来远程访问您的服务,实际上有一个内置机制来处理这种情况。
IServiceProxyFactory
当您调用( )的默认实现时,Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory
您将获得一个使用IServiceRemotingClient
. 在该的重试部分中,如果与已知结构错误相关,则与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-有关 FabricClients 中常见异常的更多详细信息,请参阅错误和异常。