当 ProductActor 尝试告诉 ValidatorActor 验证邮件时,我收到以下消息。虽然我看到了这条消息,但我得到了预期的结果。
我没有尝试从 ProductActor 向自己发送消息。为什么我仍然收到以下消息?
[INFO][5/17/2015 8:06:03 AM][Thread 0012][akka://catalogSystem/user/productActor] Message DeathWatchNotification from akka://catalogSystem/user/productActor to akka://catalogSystem/user/productActor was not delivered. 1 dead letters encountered.
- UPDATE -
下面给出了两位演员:
public class ProductActor : UntypedActor
{
protected override void OnReceive(object message)
{
if (message is ReportableStatusChanged)
{
_reportableState = ((ReportableStatusChanged) message).ReportableState;
}
else
{
if (message is RetrieveProductState)
{
var state = new ProductState()
{
ReportableState = _reportableState
};
Sender.Tell(state);
}
else
{
Context.ActorSelection("akka://ProductSystem/user/ProductActor/validator").Tell(message);
}
}
}
protected override void PreStart()
{
Context.ActorOf(Props.Create(() => new ProductValidatorActor()), "validator");
base.PreStart();
}
private IReportableState _reportableState;
}
public class ProductValidatorActor : UntypedActor
{
protected override void OnReceive(object message)
{
if (message is ChangeReportableStatus)
{
Sender.Tell(new ReportableStatusChanged(ReportableStates.ReportableState));
}
}
}
这是检查状态的测试:
class ChangeReportableStatusTest
{
public void Do()
{
var system = ActorSystem.Create("catalogSystem");
var ProductActor = system.ActorOf(Props.Create<ProductActor>(), "productActor");
ProductActor.Tell(new ChangeReportableStatus(true));
Thread.Sleep(50);
var state = ProductActor.Ask<ProductState>(new RetrieveProductState());
Console.WriteLine("Reportable State: " + (state.Result.ReportableState == ReportableStates.ReportableState ? "TRUE" : "FALSE"));
system.Shutdown();
system.AwaitTermination();
Console.WriteLine("Please press any key to terminate.");
Console.ReadKey();
}
}
答案 0 :(得分:5)
您收到了死信通知,这意味着您尝试发送的邮件无法送达。您尝试发送消息的演员可能已经死亡,或者可能从未存在过。在这种情况下,它似乎是后者。
我注意到您的ActorSystem
所在的ProductActor
的名称在您的错误消息(catalogSystem
)与您的代码(ProductSystem
)中有所不同。
使用ActorSelection
,您将错误的ActorSystem
中的演员路径发送到没有演员存在的演员路径。因此DeadLetters通知。假设ProductActor
被创建为catalogSystem
中的顶级角色,您尝试发送到的路径是正确的(/user/ProductActor/validator
),但是演员系统名称不是(应为catalogSystem
,但此处为ProductSystem
)。
那么你如何解决它?两个选项:
ActorSelection
中的正确路径,如下所示:Context.ActorSelection("akka://catalogSystem/user/ProductActor/validator").Tell(message);
。虽然这个有效,但这是错误的答案。ProductValidatorActor
创建为ProductActor
的子项,因此只需将子项的IActorRef
存储在父项中,然后直接向其发送消息。这是我推荐的方法。在这种特殊情况下,您根本不需要ActorSelection
。可以从中吸取两个教训。
ActorSelection
通常,您应Tell
向IActorRef
发送消息,而不是ActorSelection
。使用IActorRef
,您知道该角色过去曾在某个时间点存在过。这是Akka框架的保证,所有IActorRef
都存在于某个时刻,即使演员已经死了。
使用ActorSelection
,您没有这样的保证。它有点像UDP - 你只是在一个地址发消息而不知道是否有人在听。
这提出了&#34;我什么时候应该使用ActorSelection
?&#34;我遵循的准则是在{:1>}时使用ActorSelection
。
如果您需要使用ActorSelection
,请将路径放在共享类中,然后让所有其他actor引用该类。像这样:
using Akka.Actor;
namespace ProductActors
{
/// <summary>
/// Static helper class used to define paths to fixed-name actors
/// (helps eliminate errors when using <see cref="ActorSelection"/>)
/// </summary>
public static class ActorPaths
{
public static readonly ActorMetaData ProductValidatorActor = new ActorMetaData("validator", "akka://ProductActors/user/validator");
public static readonly ActorMetaData ProductCoordinatorActor = new ActorMetaData("coordinator", "akka://ProductActors/user/commander/coordinator");
}
/// <summary>
/// Meta-data class
/// </summary>
public class ActorMetaData
{
public ActorMetaData(string name, string path)
{
Name = name;
Path = path;
}
public string Name { get; private set; }
public string Path { get; private set; }
}
}
...然后可以这样引用:
Context.ActorSelection(ActorPaths.ProductValidatorActor.Path).Tell(message);