在Service Fabric中,似乎只是常见做法可能是错误的做法。我怀疑在'SomeService'有状态服务中'CreateServiceReplicaListeners()'方法的return语句中实例化'Startup'类时,下面的代码将stateManager保存为本地缓存可能会导致潜在的问题。
可能发生的情况是状态管理器以某种方式重新实例化。我需要更多解释以下练习是否是正确的做法。如果没有,那么最佳做法是什么呢?
internal class SomeService : StatefulService
{
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new[]{
new ServiceReplicaListener(
initParams =>
new OwinCommunicationListener("SomeService", new Startup(this.StateManager), initParams))
};
}
}
}
public class Startup : IOwinAppBuilder
{
private readonly IReliableStateManager stateManager;
public Startup(IReliableStateManager stateManager)
{
this.stateManager = stateManager;
}
public void Configuration(IAppBuilder appBuilder)
{
// other initialization codes..
...
...
UnityConfig.RegisterComponents(config, this.stateManager);
appBuilder.UseWebApi(config);
}
}
每当有状态服务改变角色时,它都会触发IStatefulServiceReplica.ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken)
。
ChangeRoleAsync(..)
确保新角色使用正确的通信执行以下操作:
CloseCommunicationListenersAsync(CancellationToken cancellationToken)
关闭所有打开的侦听器OpenCommunicationListenersAsync(newRole, cancellationToken)
调用为Primary或SecondarySecondary角色OpenCommunicationListenersAsync()
将调用CreateServiceReplicaListeners()
来获取侦听器并为每个返回的侦听器调用CreateCommunicationListener(serviceContext)
以打开相关端点。角色更改在升级和负载平衡期间非常常见,因此这是一个非常常见的事件。
综上所述,
每次更改角色时,都会调用CreateServiceReplicaListeners()
,ChangeRole不会关闭服务,因此可能会产生副作用,例如,如果在DI容器中注册依赖项,则可能会面临重复注册。