正确的方法如何注册自定义IStateSerializer <t>

时间:2019-04-10 11:43:24

标签: c# azure-service-fabric

自定义IStateSerializer在StatefulService生命周期中的确切注册应该在哪里进行才能有效?

internal sealed class Automat : StatefulService
{
    public Automat(StatefulServiceContext context)
        : base(context)
    { }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        var ok = this.StateManager.TryAddStateSerializer(new DeviceStateSerializer());
        if (!ok)
        {
            Log.FailedToRegisterStateSerializer();
            throw new Exception("Failed to register state serializer.");
        }

        ...
    }
}

public sealed class DeviceStateSerializer : IStateSerializer<DeviceState>
{ ... }

部署后不久,运行状况事件分区处于仲裁丢失状态。 (System.FM)被报告,并且在此状态下,有状态服务的辅助实例将发出警告:

{
  "Timestamp": "2019-04-10T13:08:10.2801059+02:00",
  "ProviderName": "Microsoft-ServiceFabric",
  "Id": 54429,
  "Message": "EventName: StatefulReplicaNewHealthReport Category: Health Partition=9396223e-01be-44fa-9b19-2438a5caec80 StatefulReplica=131993679124719148 InstanceId=131993679124719149 SourceId=System.RA Property=ReplicaOpenStatus HealthState=Warning TTL=922337203685477ms SequenceNumber=131993680683950343 Description='Replica had multiple failures during open on _Node_3. API call: IStatefulServiceReplica.Open(); Error = System.Runtime.Serialization.InvalidDataContractException (-2146233088)
    Type 'SmartGrid.Automat.Contracts.DeviceState' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.
       at Microsoft.ServiceFabric.Replicator.RecoveryManager.PerformRecoveryAsync(RecoveredOrCopiedCheckpointLsn recoveredOrCopiedCheckpointLsn, OperationProcessor recordsProcessor, CheckpointManager checkpointManager, TransactionManager transactionManager, LogRecordsDispatcher logRecordsDispatcher, ReplicatedLogManager replicatedLogManager)
       at Microsoft.ServiceFabric.Replicator.LoggingReplicator.PerformRecoveryAsync(RecoveryInformation recoveryInformation)
       at Microsoft.ServiceFabric.Replicator.DynamicStateManager.OpenAsync(ReplicaOpenMode openMode, TransactionalReplicatorSettings transactionalReplicatorSettings)
       at Microsoft.ServiceFabric.Replicator.TransactionalReplicator.OpenAsync(ReplicaOpenMode openMode, TransactionalReplicatorSettings transactionalReplicatorSettings)
       at Microsoft.ServiceFabric.Replicator.StatefulServiceReplica.System.Fabric.IStatefulServiceReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partitionObject, CancellationToken cancellationToken)
       at Microsoft.ServiceFabric.Data.ReliableStateManagerImpl.Microsoft.ServiceFabric.Data.IStateProviderReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken)
       at Microsoft.ServiceFabric.Services.Runtime.StatefulServiceReplicaAdapter.System.Fabric.IStatefulServiceReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken)
    For more information see: http://aka.ms/sfhealth' RemoveWhenExpired=False SourceUTCTimestamp=04/10/2019 13:07:48 ",
  "ProcessId": 19324,
  "Level": "Informational",
  "Keywords": "0x4000000000000001",
  "EventName": "HM",
  "ActivityID": null,
  "RelatedActivityID": null,
  "Payload": {
    "eventName": "StatefulReplicaNewHealthReport",
    "category": "Health",
    "eventInstanceId": "\"9bd354b7-0ab8-4a3d-99ce-48dbf3361432\"",
    "partitionId": "\"9396223e-01be-44fa-9b19-2438a5caec80\"",
    "replicaId": 131993679124719148,
    "replicaInstanceId": 131993679124719149,
    "sourceId": "System.RA",
    "property": "ReplicaOpenStatus",
    "healthState": 2,
    "TTLtimespan": 922337203685477,
    "sequenceNumber": 131993680683950343,
    "description": "Replica had multiple failures during open on _Node_3. API call: IStatefulServiceReplica.Open(); Error = System.Runtime.Serialization.InvalidDataContractException (-2146233088)
      Type 'SmartGrid.Automat.Contracts.DeviceState' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.
         at Microsoft.ServiceFabric.Replicator.RecoveryManager.PerformRecoveryAsync(RecoveredOrCopiedCheckpointLsn recoveredOrCopiedCheckpointLsn, OperationProcessor recordsProcessor, CheckpointManager checkpointManager, TransactionManager transactionManager, LogRecordsDispatcher logRecordsDispatcher, ReplicatedLogManager replicatedLogManager)
         at Microsoft.ServiceFabric.Replicator.LoggingReplicator.PerformRecoveryAsync(RecoveryInformation recoveryInformation)
         at Microsoft.ServiceFabric.Replicator.DynamicStateManager.OpenAsync(ReplicaOpenMode openMode, TransactionalReplicatorSettings transactionalReplicatorSettings)
         at Microsoft.ServiceFabric.Replicator.TransactionalReplicator.OpenAsync(ReplicaOpenMode openMode, TransactionalReplicatorSettings transactionalReplicatorSettings)
         at Microsoft.ServiceFabric.Replicator.StatefulServiceReplica.System.Fabric.IStatefulServiceReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partitionObject, CancellationToken cancellationToken)
         at Microsoft.ServiceFabric.Data.ReliableStateManagerImpl.Microsoft.ServiceFabric.Data.IStateProviderReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken)
         at Microsoft.ServiceFabric.Services.Runtime.StatefulServiceReplicaAdapter.System.Fabric.IStatefulServiceReplica.OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken)
      For more information see: http://aka.ms/sfhealth",
    "removeWhenExpired": false,
    "sourceUtcTimestamp": "\"\/Date(1554894468395)\/\""
  }
}

我认为它正在尝试通过使用回退到DataContractSerializer而不是未注册的DeviceStateSerializer来反序列化DeviceState。

  • Microsoft.ServiceFabric.Services 3.3.644
  • Microsoft.ServiceFabric.Services.Remoting 3.3.644
  • Microsoft.ServiceFabric.Data 3.3.644

1 个答案:

答案 0 :(得分:0)

状态串行器注册必须在ctor中,然后才能生效。

public Automat(StatefulServiceContext context)
        : base(context)
{
    var ok = this.StateManager.TryAddStateSerializer(new DeviceStateSerializer());
    if (!ok)
    {
        Log.FailedToRegisterStateSerializer();
    }
}