在 AKKA Cluster Sharding 中,可以定义多个实体角色,每种实体角色都有独立的状态和行为。我们可以在同一个集群中同时使用不同类型的实体角色。
一种方式是通过为每种实体角色定义不同的实体类型。下面是一个示例,其中我们定义了两种不同类型的实体角色:“user”和“order”。
// 实体 trait
trait Entity {
val id: String
}
// User 实体
case class UserEntity(id: String, name: String) extends Entity
// Order 实体
case class OrderEntity(id: String, product: String, quantity: Int) extends Entity
// User 实体 actor
class UserActor extends Actor with ActorLogging {
var state: UserEntity = _
def receive = {
case UpdateUser(newUser) =>
state = newUser
log.info("User updated: {}", state)
case GetUser =>
sender() ! state
}
}
// Order 实体 actor
class OrderActor extends Actor with ActorLogging {
var state: OrderEntity = _
def receive = {
case UpdateOrder(newOrder) =>
state = newOrder
log.info("Order updated: {}", state)
case GetOrder =>
sender() ! state
}
}
// 实体角色类型
sealed trait EntityType
case object UserEntityType extends EntityType
case object OrderEntityType extends EntityType
// 实体启动器
object EntityLauncher {
def launch(system: ActorSystem, entityType: EntityType, entityId: String): ActorRef = {
entityType match {
case UserEntityType =>
ClusterSharding(system).start(
typeName = "User",
entityProps = Props[UserActor],
settings = ClusterShardingSettings(system),
extractEntityId = extractUserId,
extractShardId = extractShardId
)
case OrderEntityType =>
ClusterSharding(system).start(
typeName = "Order",
entityProps = Props[OrderActor],
settings = ClusterShardingSettings(system),
extractEntityId = extractOrderId,
extractShardId = extractShardId
)
}
}
// 提取实体 ID
def extractUserId: ShardRegion.ExtractEntityId = {
case updateUser: UpdateUser => (updateUser.id, updateUser)
case getUser: GetUser => (getUser.id, getUser)
}
def extractOrderId: ShardRegion.ExtractEntityId = {
case updateOrder: UpdateOrder => (updateOrder.id, updateOrder)
case getOrder: GetOrder => (getOrder.id, getOrder)
}
// 提取分片