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