简体   繁体   English

如何处理演员内的异常?

[英]How to handle exceptions within the actor?

Is there a standard pattern to deal with exceptions within actors in Akka.NET? 是否有一个标准模式来处理Akka.NET中的参与者中的异常?

I saw some patterns to create supervisors, but it seems the SupervisorStrategy is a way to deal with things that cannot be resolved by the actor. 我看到了一些模式来创建主管,但似乎SupervisorStrategy是一种处理演员无法解决的事情的方法。

I have an actor that receives lots of data and needs to store it in an external server. 我有一个接收大量数据的actor,需要将它存储在外部服务器中。 The external database may be unreachable. 外部数据库可能无法访问。 If it is, the server may be restarting or the network may be down. 如果是,则服务器可能正在重新启动或网络可能已关闭。 I don't need to restart the actor or anything, I just want to notify the sender with some information about what is happening, so he can persist the message on disk and reschedule for later. 我不需要重新启动演员或任何东西,我只想通知发件人一些有关正在发生的事情的信息,因此他可以将消息保留在磁盘上并重新安排以供日后使用。

The sender is not a parent of this actor connecting to the database. 发件人不是连接到数据库的此actor的父级。 Should I create a supervisor just to handle this as well? 我应该创建一个主管来处理这个问题吗? Or should I encapsulate my receive handlers in try/catch blocks and just use Tell to notify the senders a with a custom response as if it was a normal message? 或者我应该将我的接收处理程序封装在try / catch块中,然后使用Tell通过自定义响应通知发件人a,就好像它是正常的消息一样?

I know there is a Failure class, but I'm not sure if I'm suppose to use that for this situation. 我知道有一个Failure类,但我不确定我是否想在这种情况下使用它。

Yes there is. 就在这里。 First of all, always delegate dangerous work to child actors, give them all your knifes, flame thrower and such. 首先,总是将危险的工作委托给儿童演员,给他们所有的刀,火焰喷射器等。 if they crash and burn, your state is still intact and you can spawn new children. 如果他们崩溃和燃烧,你的状态仍然完好,你可以产生新的孩子。

So for the unreachable database example; 所以对于无法访问的数据库示例; Spin up a DB-communication actor. 启动数据库通信演员。 You can then let this actor have two states, DB up and DB down, this can be modeled as an FSM or using Become / Unbecome . 然后你可以让这个actor有两个状态,DB up和DB down,这可以建模为FSM或使用Become / Unbecome

So when a message arrives and requesting a DB query, if things blow up, the DB communicator actor puts it self into DB-Down state. 因此,当消息到达并请求数据库查询时,如果事情爆发,则数据库通信器参与者将其自身置于DB-Down状态。 If any query is received in DB-Down state, you can immediately respond with a Failure event. 如果在DB-Down状态下收到任何查询,您可以立即响应Failure事件。

So how do we go from DB-Down to to DB-Up again? 那么我们如何再次从DB-Down转到DB-Up? The DB-Communicator actor can ping it self using ScheduleOnce , eg pass it self a "CheckDBStatus" message every x seconds. DB-Communicator actor可以使用ScheduleOnce自行ping它,例如每x秒传递一次“CheckDBStatus”消息。 When the CheckDBStatus message is received, you check if DB is up again, and if so, you revert back to DB-Up state. 收到CheckDBStatus消息后,检查DB是否再次启动,如果是,则恢复为DB-Up状态。

This way, you will not flood your DB in scenarios where it is unable to respond due to high load, adding more load in that case will only make things worse. 这样,在高负载无法响应的情况下,您不会充斥数据库,在这种情况下添加更多负载只会使事情变得更糟。 So this kind of circuit breaker will prevent that from happening. 所以这种断路器可以防止这种情况发生。

So in short: 简而言之:

In DB-Up state: 在DB-Up状态:

If a DBQuery message is received, try to run the query, and send back the response. 如果收到DBQuery消息,请尝试运行查询,然后发回响应。 if things blow up, go directly to DB-Down state and respond with a failure event. 如果事情爆发,直接进入DB-Down状态并以失败事件响应。

In DB-Down state: if a DBQuery message is received, respond with a Failure event directly w/o touching the DB. 在DB-Down状态:如果收到DBQuery消息,则直接响应Failure事件而不接触DB。 Ping yourself every x seconds to see if DB is up, and revert to DB-Up state if possible. 每隔x秒ping一次以查看DB是否已启动,并在可能的情况下恢复为DB-Up状态。

In this scenario, you would not use any supervisor to transit the state, normal try/catch would be enough to deal with this. 在这种情况下,您不会使用任何主管来传输状态,正常的try / catch就足以解决这个问题。

Hope this clear things up. 希望这清楚的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM