Orleans 2.0 官方文档 —— 4.10.4 Grains -> 高级功能 -> 无状态工作器grain

无状态工作器 Grain

默认情况下,Orleans运行时在集群创建的grain激活体不超过一个。这是Virtual Actor模型的最直观的表达,每个grain对应于具有唯一类型/标识的实体。但是,也有一些情况下,应用程序需要执行与系统中的特定实体无关的、功能性的无状态操作。例如,如果客户端发送的请求中带有被压缩的有效负载,则需要将其解压缩,然后才能将其路由到目标grain进行处理,则此类解压缩/路由逻辑不会绑定到应用程序中的特定实体,并且可以很容易地扩展。

[StatelessWorker]属性应用于grain类时,它向Orleans运行时指示,应将该类的grain视为无状态工作器 grain。 无状态工作器 grain 具有以下特性,使得它们的执行,大大不同于普通grain类的执行。

  1. Orleans运行时,既可以,又会在集群的不同silo上,创建多个无状态工作器grain的激活体。
  2. 对无状态工作器grain的请求总是在本地执行,即在发出请求的同一个silo中。此请求要么发出自silo上运行的grain,要么接收自silo上的客户端网关。因此,从其他grain或客户端网关调用无状态工作者grain,绝不会招致远程信息。
  3. 如果现有的grain繁忙,Orleans运行时会自动创建无状态工作器grain的额外激活体。除非由可选的maxLocalWorkers参数显式地指定,否则默认情况下,运行时为每个silo创建的无状态工作器grain的最大激活体的数量,受限于计算机上的CPU核心数。
  4. 由于2和3的原因,无状态工作器grain激活体不能单独寻址。对无状态工作器grain的两个后续请求,可能被它的不同的激活来体处理。

无状态工作grain,提供了一种简单的方式,来创建自动管理的grain激活池,该池根据实际负载自动扩大和缩小。运行时始终以相同的顺序,扫描可用的无状态工作者grain激活体。因此,它总是将一个请求,分派给它可以找到的第一个空闲的本地激活体,并且只有在所有前面的激活体都忙的情况下,才会到达最后一个。如果所有激活体都忙,并且尚未达到激活体的数量限制,则会在列表末尾再创建一次激活体,并将请求发送给它。这意味着,当对无状态工作者grain的请求率增加,并且现有激活当前都处于忙碌状态时,运行时会将其激活池扩展到最大限度。相反,当负载下降时,并且可以通过少量无状态工作者grain的激活体来处理,列表尾部的激活体不会收到发送给他们的请求。它们将变为空闲状态,并最终由标准激活收集过程停用。因此,激活池最终将缩小以匹配负载。

以下示例,使用默认的最大激活数限制,定义了一个无状态工作grain类MyStatelessWorkerGrain

[StatelessWorker]
public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
{
 ...
}

调用无状态工作grain,与调用任何其他的grain一样。唯一的区别是在,大多数情况下使用单个grain ID,0或Guid.Empty。当需要使用多个无状态工作grain池(每个ID一个),可以使用多个grain ID。

var worker = GrainFactory.GetGrain(0);
await worker.Process(args);

这个定义了一个无状态工作grain类,每个silo只有一个grain 激活体。

[StatelessWorker(1)] // max 1 activation per silo
public class MyLonelyWorkerGrain : ILonelyWorkerGrain
{
 ...
}

请注意,[StatelessWorker]属性不会更改目标grain类的可重入性。就像任何其他grain一样,无状态工作默认情况下是不可重入的。通过向grain类添加[Reentrant]属性,可以显式地使它们成为可重入的。

状态

“无状态工作”的“无状态”部分并不意味着无状态工人不能拥有状态,且限于执行功能性操作。与任何其他grain一样,无状态工作器grain可以将它需要的任何状态,加载并保存在内存中。这仅仅是因为,可以在集群的同一个和不同的silo上,创建无状态工作的多个激活体,而没有简单的机制,来协调不同激活体所持有的状态。

涉及到无状态工作器持有状态,有几种有用的模式。

扩展热缓存项目

对于经受高吞吐量的热缓存项目,在无状态工作器grain中持有每个此类项目,能使得:a)在一个silo内以及跨集群中的所有silo中,实现自动扩展; b)在silo的本地,使数据始终可用,该silo通过其客户端网关接收客户端请求,这样便可以在没有额外网络跳转到另一个孤岛的情况下,就能响应请求。

reduce方式的聚合

在某些场景下,应用程序需要计算群集中特定类型的所有grain的某些度量,并定期报告聚合。例如,报告每个游戏地图的玩家数量,VoIP呼叫的平均持续时间等。如果数千或数百万个grain中的每一个,都将其指标报告给单个全局聚合器,则聚合器将立即过载,无法处理大量的报告。另一种方法是,将此任务转换为2步骤(或更多)的reduce方式的聚合。通过报告grain将其指标发送给无状态工作器预聚合的grain,来完成第一层聚合。Orleans运行时将自动为每个silo创建多个无状态工作器grain的激活体。由于所有这些调用都将在本地处理,而不进行远程调用或消息序列化,因此这种聚合的成本将远远低于远程情况下的成本。现在,每个预聚合无状态工作器grain的激活体,独立地或与其他本地激活体协调,可以将其聚合报告,发送到最终的全局聚合器(或必要时发送到另一个reduce层),而不会使其超载。

你可能感兴趣的:(Orleans)