2017-05-27 1 views
0

私はAkka.NETの俳優にIActorRefを含むオブジェクトであるメッセージを送信し、そのメッセージを解決しない場合は、ジャーナルテーブルに書き込まれたJSONは次のようになります。私はこれを理解していた場合Akka.NETの永続性は、IActorRefを含むメッセージの再生をどのように処理しますか?

{"$id":"1","$type":"LearningAkka.Program+BindReference, LearningAkka","Reference":{"$id":"2","$type":"Akka.Actor.ActorRefBase+Surrogate, Akka","Path":"akka://LearningAkka/user/$b#1222898859"}} 

これは単にアクタのインスタンスへの参照です。それを作成するために必要な「小道具」はこのメッセージに格納されません。

奇妙なことに、私はです。アプリを再起動した後にオブジェクトが表示されます。しかし、予想どおり、再起動前に構築されたものではありません。この俳優はどこから来たのですか? Akka Persistenceは「十分に似ている」俳優を見つけて代わりに使用しましたか?

次のC#テストアプリケーションはオブジェクトを作成し、それを3つのうちの1つにバインドするメッセージを送信します。アクターシステムを廃棄した後、そのオブジェクトは永続性(SQL Server)から再作成され、参照がチェックされます。

は私の予想される動作は、以下の(私が最も適切だかわからないんだけど)のいずれかである:そのメッセージのいずれかが、解決不能の参照が含まれているため

  • 俳優が作成することはできません。
  • アクター参照は解決できないため、nullです。
  • 俳優の参照先がデッドレターなどを指しています。

コンソール出力:

[WARNING][27/05/2017 21:02:27][Thread 0001][ActorSystem(LearningAkka)] NewtonSoftJsonSerializer has been detected as a default serializer. It will be obsoleted in Akka.NET starting from version 1.5 in the favor of Hyperion (for more info visit: http://getakka.net/docs/Serialization#how-to-setup-hyperion-as-default-serializer). If you want to suppress this message set HOCON `akka.suppress-json-serializer-warning` config flag to on. 
From the first run B 

[WARNING][27/05/2017 21:02:28][Thread 0001][ActorSystem(LearningAkka)] NewtonSoftJsonSerializer has been detected as a default serializer. It will be obsoleted in Akka.NET starting from version 1.5 in the favor of Hyperion (for more info visit: http://getakka.net/docs/Serialization#how-to-setup-hyperion-as-default-serializer). If you want to suppress this message set HOCON `akka.suppress-json-serializer-warning` config flag to on. 
From the second run B 

C#:

using Akka.Actor; 
using Akka.Event; 
using Akka.Persistence; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace LearningAkka 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var actorSystem = ActorSystem.Create("LearningAkka")) 
      { 
       var referenceA = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run A"))); 
       var referenceB = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run B"))); 
       var referenceC = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run C"))); 
       var actor = actorSystem.ActorOf(Props.Create(() => new TestActor())); 
       actor.Tell(new BindReference { Reference = referenceB }); 
       actor.Tell(new CheckReference()); 
       Console.ReadLine(); 
      } 

      using (var actorSystem = ActorSystem.Create("LearningAkka")) 
      { 
       var referenceA = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run A"))); 
       var referenceB = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run B"))); 
       var referenceC = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run C"))); 
       var actor = actorSystem.ActorOf(Props.Create(() => new TestActor())); 
       actor.Tell(new CheckReference()); 
       Console.ReadLine(); 
      } 
     } 

     public struct BindReference { public IActorRef Reference; } 
     public struct CheckReference { } 

     public sealed class TestActor : ReceivePersistentActor 
     { 
      public override string PersistenceId => "test hardcoded"; 

      private IActorRef StoredFromMessage; 

      public TestActor() 
      { 
       Command<CheckReference>(m => StoredFromMessage.Tell(m)); 
       Command<BindReference>(m => Persist(m, m2 => StoredFromMessage = m2.Reference)); 
       Recover<BindReference>(m => StoredFromMessage = m.Reference); 
      } 
     } 

     public sealed class TestReferencedActor : ReceiveActor 
     { 
      public TestReferencedActor(string ourLabel) 
      { 
       Receive<CheckReference>(m => Console.WriteLine(ourLabel)); 
      } 
     } 
    } 
} 

HOCON:

 akka { 
     persistence { 
      journal { 
      plugin = "akka.persistence.journal.sql-server" 
      sql-server { 
       class = "Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer" 
       connection-string = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=LearningAkka;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" 
       schema-name = dbo 
       table-name = Journal 
       auto-initialize = on 
      } 
      } 
      snapshot-store { 
      plugin = "akka.persistence.snapshot-store.sql-server" 
      sql-server { 
       class = "Akka.Persistence.SqlServer.Snapshot.SqlServerSnapshotStore, Akka.Persistence.SqlServer" 
       connection-string = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=LearningAkka;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" 
       schema-name = dbo 
       table-name = Snapshot 
       auto-initialize = on 
      } 
      } 
     } 
     } 

誰かがここに行動にコメントしてくださいもらえますか?ありがとうございました。

+0

イベントの再生時にアクター参照を取得できない場合、 'IActorRef'はデッド文字を指します。 akka.loglevelをDEBUGにすると、その参照を介して送信されたメッセージがそこに着くことがわかります。 – Horusiath

+0

それはまさに私が期待しているものですが、私が見ているものではありません。上記のように、IActorRefは、新しいアクターシステムの作成以来作成された無関係のアクターを指しているように見えます。私が第1俳優システムで作成された第2俳優への参照を保持している場合、回復時に、第2俳優システムで作成された第2俳優への参照が得られます。 – jameswilddev

答えて

0

シリアル化データからわかるように、IActorRefはこのアドレスakka://LearningAkka/user/$bを指しています。通常、無名の俳優には$bが配置されます。だから、あなたが俳優のシステムルート(私が知る限り)で作成した名前のない2番目の俳優は、常にそれになります。

あなたは正しいので、システムの動作はここでは定義されていません。

関連する問題