从技术上讲,两者兼而有之。
因为actors是单线程的,所以actor中只能同时发生一个操作。
SF Actor 使用 Ask 方法,每个呼叫都期待一个应答,调用者将拨打电话并一直等待应答,如果该 Actor 收到来自客户端的太多呼叫,并且该 Actor 过于依赖外部组件,它处理每个调用将花费太长时间,并且所有其他客户端调用将被排队,并且可能会在某些时候失败,因为它们将等待太长时间并超时。
这对于使用 Tell 方法的参与者来说不是什么大问题,比如 Akka,因为它不等待答案,它只是将消息发送到邮箱并接收带有答案的消息(如果适用) .但是请求和响应之间的延迟仍然是一个问题,因为有太多消息等待单个参与者处理。另一方面,如果一个命令失败,可能会增加复杂性,并且在您知道第一个命令的答案之前触发了 2 或 3 个事件序列(不是这里的范围,但您将这种情况与下面的示例联系起来)。
关于第二点,Actor 的主要思想是自包含,如果过于依赖外部依赖,也许你应该重新考虑设计并评估 Actor 是否真的是解决问题的最佳设计。
自包含的 Actor 是可扩展的,它们不依赖外部状态管理器来管理自己的状态,它们不会依赖其他 Actor 来完成它们的任务,它们可以相互独立地扩展。
例子:
Actor1(属于 ActorTypeA)依赖于 Actor2(属于 ActorTypeB)来执行一个操作。
为了让它更人性化,让我们说:
- ActorTypeA 是电子商务结帐车
- ActorTypeB 是股票管理公司
- Actor1 是用户 1 的购物车
- Actor2 是产品 A 的 Stock
每当客户(用户)与其结账购物车交互、添加或删除产品时,它都会向 Actor1 发送添加和删除命令以管理他自己的购物车。在这种情况下,依赖是一对一的,当另一个用户导航到该网站时,将创建另一个参与者来管理他自己的购物车。在这两种情况下,他们都会有自己的演员。
现在假设,每当将产品放入购物车时,都会保留库存以避免重复销售相同的产品。
在这种情况下,两个actor都会尝试在actor2中保留产品,由于actor的单线程特性,只有第一个会成功,第二个会等待第一个完成,如果产品没有库存,则失败了。此外,第二个用户将无法在他的购物车中添加或删除任何产品,因为第一个操作正在等待完成。现在将这些数字增加到数千,看看问题是如何迅速发展的,而可扩展性却失败了。
这只是一个小而简单的例子,所以,第二点不仅适用于外部依赖,它也适用于内部依赖,actor外部的每个操作都会降低它的可伸缩性。
也就是说,你应该尽可能地避免外部(actor外部)依赖,但如果需要它不是犯罪,但是当外部依赖限制它独立扩展时,你会降低可扩展性。
This other SO question我已经回答了你可能也会感兴趣。