如何在复杂的后端服务中使用actors,这些服务包括接收初始请求,进行一些处理,然后将一些请求/待办事项发送到其他服务,等待来自其中一些,并根据答案决定如何继续,等等,直到我们计算出最终结果?
尝试使用actor来实现此类服务提出了一个问题 - 演员应该实现此工作流的哪些部分,哪些部分不应该?
Actor实例不会释放他们正在使用的线程,直到他们尝试完成的任务完成(除非我们将它委托给Future),因此我认为将整个工作流程编写为越来越小的层次结构具有N层儿童的演员一方面将是基于演员概念的理想设计,但另一方面,它将保持N-1个线程(每个初始请求) - 不断锁定什么,只需等待一个完成层次结构中的底层角色。具体来说,层次结构中最顶层的actor将在大多数时间处于空闲状态。
此分层设计也与error kernel模式匹配。
但这对于并发来说听起来非常糟糕。
即使你试图保留这个actor的层次结构,但是将调用包装在Future中的每个actor(通过询问子actor,而不是告诉),所以锁定会更短(尽管它仍然存在) - 仍然使用如此多的Futures使得无法与有状态的演员或演员以不同步的方式修改系统状态(即不仅仅是修改数据库,至少对于简单的请求是自动完成的)通过数据库事务 - 而是在应用程序中修改一些全局变量。)
演员是否应仅在工作流程的较低级别使用?
或者应该以更加连续的方式重写层次(大多数)的工作流程,因此它不需要这么多级别的儿童演员(但这将是相当困难和不自然的,并且似乎给予了实施框架对设计的影响太大了。)
这意味着你意识到演员是非常有限的,并且失败容忍度应该主要由传统的异常处理来处理,并且在任何情况下,拥有容错应用程序的愿望不应该对设计的应用程序。 在那种情况下,为什么要与演员一起打扰?使用需要阅读每个actor的实现以便理解复杂的意大利面条式消息结的工作流程的框架,比使用基于层次结构的框架更容易,这些框架可以通过任何所需的程度显示查看方法签名,而不必盯着它们的实现。
如果只有一小部分应用程序是由演员实现的,那么演员的许多好处,例如易于扩展,似乎不太相关或不实用。
答案 0 :(得分:0)
我认为你对演员中“锁定”的理解是不正确的。
你写
但另一方面它会保持N-1个线程(每个初始值 请求) - 经常无所事事
目前还不清楚你在这里描述的场景。正在使用的线程数不是由actor层次结构中的actor或层数决定的,而是由运行actor的调度程序决定的,请参阅https://doc.akka.io/docs/akka/2.5/dispatchers.html?language=scala
一个actor通常不会生成一个新线程,也不会在它空闲时阻塞任何东西。它将处理(可配置的)数量的消息,然后将控制权交还给调度程序。因此,就多线程而言,与您所怀疑的相反,Akka非常有效。
如果您尝试保留此actor的层次结构,但将调用包装起来 未来的每个演员(通过询问儿童演员,而不是 告诉),所以锁定会更短
那里肯定会有一些误解。向另一个发送消息的actor不会阻塞线程。目前还不清楚你所指的是什么“锁定”。此外,ask
使锁定更短的假设显然是有缺陷的,因为没有锁定。
也许您担心的是使用来自演员的阻止IO?这确实会阻止执行线程。这里的“技巧”是将阻塞调用放在单独的调度程序上,请参阅https://doc.akka.io/docs/akka/snapshot/dispatchers.html?language=scala