【发布时间】:2017-11-21 02:49:08
【问题描述】:
actors 如何用于复杂的后端服务,即接收初始请求,进行一些处理,然后将一些请求/待办事项发送到其他服务,等待来自某些服务的响应他们,并根据响应决定如何继续,等等,直到我们计算出最终结果?
尝试使用参与者来实现此类服务提出了一个问题 - 该工作流程的哪些部分应该由参与者实现,哪些部分不应该?
Actor 实例在他们试图完成的任务完成之前不会释放他们正在使用的线程(除非我们将它委托给 Future),所以在我看来,它就像将整个工作流编写为一个越来越小的层次结构具有 N 层子节点的演员,一方面是基于演员概念的理想设计,但另一方面它将保持 N-1 个线程(每个初始请求) - 不断锁定,除了等待一个线程之外什么都不做层次结构中的底层参与者来完成。具体来说,层次结构中最顶层的参与者大部分时间都是空闲的。
这种分层设计也符合error kernel 模式。
但这听起来对并发非常不利。
即使你试图保持这个actors的层次结构,但是将每个actor的调用包装在一个Future中(通过询问子actors,而不是告诉子actors),所以锁定会更短(尽管它仍然存在) - 仍然使用如此多的 Futures 使得不可能与有状态的参与者合作,或者以自己不同步的方式修改系统状态的参与者(即不简单地修改数据库,至少对于简单的请求是自动完成的)通过数据库事务 - 而是修改应用程序中的一些全局变量)。
那么演员应该只用在工作流的较低级别吗?
或者应该以更连续的方式重写主要是分层的(并且大多数是)的工作流程,因此它不需要这么多级别的子演员(但这会非常困难和不自然,并且似乎给实现框架对设计影响太大)。
这意味着您认识到参与者非常有限,并且容错应该主要由传统的异常处理来处理,并且无论如何,拥有容错应用程序的愿望不应该对应用程序的设计。 既然如此,何必找演员呢?使用一个需要阅读每个参与者的实现以理解复杂的意大利面条状消息结的工作流程的框架,比使用基于层次结构的框架要容易得多查看方法签名,而不必查看它们的实现。
如果应用程序的一小部分由参与者实现,参与者的许多好处(例如易于横向扩展)似乎不太相关或不实用。
【问题讨论】:
标签: multithreading error-handling akka actor error-kernel