当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.
Run Code Online (Sandbox Code Playgroud)
--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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是检查状态的测试:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
您收到了死信通知,这意味着您尝试发送的邮件无法送达.你试图发送消息的演员可能已经死了,或者它可能从未存在过.在这种情况下,它似乎是后者.
我注意到的名字ActorSystem,你的ProductActor生活中是在错误消息中不同的(catalogSystem)对你的代码(ProductSystem).
有了你ActorSelection,你就会向一个错误的演员路径发送一条消息到一个ActorSystem没有演员存在的演员路径.因此DeadLetters通知.假设ProductActor创建为顶级actor,catalogSystem您尝试发送的路径是正确的(/user/ProductActor/validator),但是actor系统名称不是(应该在catalogSystem这里ProductSystem).
那么你如何解决它?两种选择:
ActorSelection喜欢中使用正确的路径:Context.ActorSelection("akka://catalogSystem/user/ProductActor/validator").Tell(message);.虽然这有效,但这是错误的答案.ProductValidatorActor了子项ProductActor,只需将IActorRef子项存储在父项中,并直接向其发送消息.这是我推荐的方法.在这种特殊情况下,您根本不需要ActorSelection.这有两个教训.
ActorSelection时不需要它通常,您应该将Tell消息发送到IActorRefs而不是ActorSelections.有了IActorRef,你知道演员在过去的某个时间点存在过.这是Akka框架的保证IActorRef,即使演员现在已经死了,所有这些都存在于某个时刻.
有了ActorSelection,你没有这样的保证.它有点像UDP - 你只是在地址上发送消息而不知道是否有人在听.
这提出了"我ActorSelection什么时候应该使用?"的问题.我遵循的准则是使用ActorSelection时间:
如果需要使用ActorSelections,请将路径放在共享类中,然后让所有其他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; }
}
}
Run Code Online (Sandbox Code Playgroud)
...然后可以这样引用:
Context.ActorSelection(ActorPaths.ProductValidatorActor.Path).Tell(message);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1158 次 |
| 最近记录: |