角色介绍
Dapr运行时提供了基于虚拟角色模式的角色实现。Dapr角色API提供了一个单线程编程模型,该模型结合了Dapr所运行的底层平台所提供的可伸缩性和可靠性保证。
什么是角色?
角色是一个单独的、独立的计算和状态单元,它使用单线程执行。
角色模式是并发或分布式系统的一种计算模式,它允许大量的角色同时并相互独立地运行。角色之间可以相互通讯,也可创建更多的角色。
什么时候使用角色
Dapr角色实现了角色设计模式。与其它软件设计模式一样,是否使用某种特定的设计模式取决于软件设计的目的是否适合该模式。
尽管角色设计模式可以很好地适应大多数分布式系统问题及场景,也必须谨慎考虑该模式的约束条件以及一定要实现的框架。通常情况下,满足以下场景可考虑使用角色模式:
- 你的问题空间包含大量(上千或更多)小的、无依赖的、独立的状态及逻辑单元。
- 你想要以单线程对象方式工作,它无需与外部组件的重要交互(包括查询一系列角色的状态)。
- 你的角色实例不会通过I/O操作来阻塞调用者,造成不可预知的延迟。
Dapr中的角色
每一个角色是一种角色类型的一个实例,就像对象是一种类的实例一样。例如,有一种实现了计算功能的角色类型,它对应的角色实例可能分布到集群中的多个节点上。每一个角色由唯一的角色ID标识。
角色生命周期
Dapr角色是虚拟的,这意味着它的生命周期与它的内存表示无关。也就是说,它们无需显式地创建或销毁。Dapr角色运行时在第一次收到某个角色ID时,将会自动创建角色实例。如果一个角色在一段时间内未被使用,Dapr角色运行时将回收内存中的对象。同时,运行时也会维持那些需要在之后重新激活的角色状态。有关更多信息,参考角色生命周期及垃圾回收。
作为虚拟角色模型的结果,这种虚拟角色生命周期抽象带来了一些警告,实际上Dapr实现的角色模式有时候会偏离这个模型。
角色是自动激活的(引发一个角色对象被构造),这发生在首次收到角色ID的消息请求。在过一段时间之后,角色对象被回收,之后,如果再次使用这个角色ID,将会再次构造一个角色对象,由于角色的状态是存放到Dapr运行时中所配置的状态提供器中,所以它存在的时间会比角色实例对象本身更长。
分布式及故障转移
为了提供可伸缩性及可靠性,角色实例分布到整个集群中,并根据需要自动将它们从故障节点迁移到正常节点。
角色分布到角色服务的各个Pod中,这些Pod分布到集群中的不同节点。每一个服务实例包含一组角色。
Dapr角色运行时管理分配方案以及键区间,这简化了选择,但也带来了一些考虑:
- 默认情况下,角色被随机放置到Pod中以便实现均匀分布。
- 由于角色是随机分配,这将导致角色的操作总是需要网络通信,包括序列化及反序列化,这会增加延迟的开销。
角色间通讯
你可以通过Http/gRPC终结点来调用角色方法。
POST/GET/PUT/DELETE http://localhost:3500/v1.0/actors/<actorType>/<actorId>/method/<method>
你可以在请求体中提供调用角色方法的任何数据,而请求的响应体中会包含调用角色的应答数据。
参考 dapr规范了解更多详情。
并发
Dapr角色运行时提供了简单的回合制模型来访问角色方法,这意味着在角色对象内部,在任何时候都不可能有超过一个线程。回合制访问极大地简化了并发系统而无需考虑数据访问的同步机制。这也意味着在设计系统时,必须考虑每个角色的单线程访问特性。
单个角色实例在同一时间无法处理超过一个的请求,如果希望角色实例处理并发请求,则它可能导致吞吐量瓶颈。
如果两个角色之间有相互调用,而角色同时向对方发出外部请求,那么角色之间可能会出现死锁。Dapr角色运行时将会自动超时角色调用,并向调用者抛出异常来中断可能的死锁情况。
回合制的访问
一个回合包含完整地执行一个角色方法来响应其他角色或客户端的请求,或者完整地执行一个定时器/唤醒回调。即使这些方法和回调是异步的,Dapr运行时也不会交错他们。一个回合必须完全完成之后才允许开始新的回合。换句话说,当前执行的角色方法或定时器/唤醒回调必须全部完成后,才会处理下一个新的方法或回调。如果从该方法或回调返回的执行已经完成,并且该方法或回调返回的任务已经完成,则认为该方法或回调已经完成,值得强调的是,即使在不同的方法、定时器和回调之间,基于回合的并发也是必须的。
Dapr actor运行时通过在回合开始时获取每个角色的锁并在轮询结束时释放锁来实现基于回合的并发性。因此,基于回合的并发性是在每个角色的基础上实现的,而不是在角色之间。在不同角色中的方法以及定时器/唤醒回调可以同时执行。
以下示例阐述了上述概念,一个角色类型实现了两个异步方法(即,Method1及Method2),一个定时器,一个唤醒器。下图显示了代表属于这个角色类型的两个参与者(ActorId1和ActorId2)执行这些方法和回调的时间线示例。