我正在查看Akka.net faulttolerance,并设置了一个简单的示例,其中Actor1告诉Actor2一条消息。 Actor2抛出异常。 Actor1有一个SuperVisorStrategy,告诉失败的actor恢复。
我实际上预计该消息将再次传递给Actor2。但事实并非如此。所以Actor2恢复并可以继续处理新消息。 但是现在让演员失败的消息已经消失了。应如何处理?我不想丢失导致异常的消息。我希望Actor2再次处理该消息。
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
using (ActorSystem actorSystem = ActorSystem.Create("test"))
{
IActorRef customer = actorSystem.ActorOf(Props.Create<Actor1>(), "actor1");
customer.Tell(new Start());
Console.Read();
}
}
}
public class Actor1 : UntypedActor
{
protected override SupervisorStrategy SupervisorStrategy()
{
return new OneForOneStrategy(3, TimeSpan.FromSeconds(5), ex =>
{
if (ex is ApplicationException)
return Directive.Resume;
return Directive.Escalate;
});
}
protected override void OnReceive(object message)
{
if (message is Start)
{
IActorRef actor2Ref = Context.ActorOf<Actor2>("actor2");
Context.Watch(actor2Ref);
actor2Ref.Tell(new DoSomething());
}
else if (message is Response)
{
Console.WriteLine("Response received");
return;
}
else if (message is Terminated)
{
Console.WriteLine("Terminated");
}
}
}
public class Actor2 : UntypedActor
{
protected override void OnReceive(object message)
{
if (message is DoSomething)
{
// only called once.
throw new ApplicationException("testexception");
}
}
}
public class Start
{
}
public class DoSomething
{
}
public class Response
{
}
}
答案 0 :(得分:2)
通常,您不太可能连续多次重新处理相同的容易出错的消息。如果它导致异常,在同一毫秒内反复处理它可能会带来完全相同的结果。
可能想要实现的目标是在一段时间后尝试重新处理它,即因为您尝试重新连接到外部服务。在这种情况下,您可能希望将其包装到另一个消息中,并在ActorSystem调度程序中安排重新发送。基本示例:
sealed class Retry
{
public readonly object Message;
public readonly int Ttl;
public Retry(object message, int ttl)
{
Message = message;
Ttl = ttl;
}
}
class MyActor : ReceiveActor
{
...
protected override void PreRestart(Exception reason, object message)
{
Retry oldRetry;
var retry = (oldRetry = message as Retry) != null
? new Retry(oldRetry.message, oldRetry.Ttl - 1)
: new Retry(message, retryCount);
if (retry.Ttl > 0)
Context.System.Scheduler.ScheduleTellOnce(delay, Self, retry, Sender);
base.PreRestart(reason, message);
}
}
根据您的需要,其他一些案例也可能涉及使用CircuitBreakers或更可靠的传递语义 - 默认情况下,Akka.NET提供最多一次传递语义,您可以使用Akka.Persistence中的AtLeastOnceDelivery组件来更改此信息。插件。