私は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
}
}
}
}
誰かがここに行動にコメントしてくださいもらえますか?ありがとうございました。
イベントの再生時にアクター参照を取得できない場合、 'IActorRef'はデッド文字を指します。 akka.loglevelをDEBUGにすると、その参照を介して送信されたメッセージがそこに着くことがわかります。 – Horusiath
それはまさに私が期待しているものですが、私が見ているものではありません。上記のように、IActorRefは、新しいアクターシステムの作成以来作成された無関係のアクターを指しているように見えます。私が第1俳優システムで作成された第2俳優への参照を保持している場合、回復時に、第2俳優システムで作成された第2俳優への参照が得られます。 – jameswilddev