akka 集群 Sharding分片

分片上下级结构

集群(多台节点机) —> 每台节点机(1个片区) —> 每个片区(多个分片) —> 每个分片(多个实体)

实体: 分片管理的 Actor
Shards :分片是统一管理的一组实体
ShardRegion : 片区,部署在每个集群节点上,对分片进行管理
ShardCoordinator : cluster-singleton 集群单例, 决定分片属于哪个片区

工作原理

ShardRegion 在节点上启动

带实体ID的消息--> 片区ShardRegion ,请求分片位置-->ShardCoordinator-->决定哪个ShardRegion将拥有Shard-->

ShardRegion 确认请求并创建 Shard supervisor 做为子actor -->shard actor 创建 entity -->ShardRegion和Shard 定位entity

分区的分片规则

所有片区组成分布式分片管理层,带实体ID的消息直接发给本机片区,分片管理层路由消息, ShardRegion创建需要提供基于ShardRegion.MessageExtractor的实现 ,必须提供从消息抽取分片和实体ID的函数

示例实现

package shard

import akka.actor.AbstractActor
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.cluster.sharding.ClusterSharding
import akka.cluster.sharding.ClusterShardingSettings
import akka.cluster.sharding.ShardCoordinator
import akka.cluster.sharding.ShardRegion
import akka.japi.Option
import akka.japi.pf.ReceiveBuilder
import com.typesafe.config.ConfigFactory
import org.slf4j.LoggerFactory
import java.io.Serializable
import java.time.Clock.system
import java.time.Clock.system
import java.util.*
import java.time.Clock.system /**
* Created by: tankx
* Date: 2019/7/16
* Description: 集群分片示例
*/ //分布到集群环境中
class DogActor : AbstractActor() { var log = LoggerFactory.getLogger(DogActor::class.java) override fun createReceive(): Receive {
return ReceiveBuilder.create().matchAny(this::receive).build()
} fun receive(obj: Any) { log.info("收到消息: $obj")
if (obj is DogMsg) {
log.info("${obj.id} ${obj.msg}")
} } } //定义消息(必须带有实体ID进行分片)
data class DogMsg(var id: Int, var msg: String) : Serializable //分片规则
class ShardExtractor : ShardRegion.MessageExtractor {
//提取实体ID,实体对应的actor
override fun entityId(message: Any?): String {
if (message is DogMsg) {
return message.id.toString()
} else {
throw RuntimeException("无法识别消息类型 $message")
}
} //根据实体ID,计算出对应分片ID
override fun shardId(message: Any?): String {
//var numberOfShards: Int = 10 //简单的分区数取模 return message.id%numberOfShards
if (message is DogMsg) {
//return (message.id % 10).toString()
return message.id.toString()
} else {
throw RuntimeException("无法识别消息类型 $message")
}
} //对消息可进行拆封操作
override fun entityMessage(message: Any): Any {
return message
} }
//分区停止时会派发的消息类型
object handOffStopMessage fun createActorSystem(port: Int): ActorSystem {
val config = ConfigFactory.parseString(
"akka.remote.artery.canonical.port=$port"
).withFallback(
ConfigFactory.load()
) var actorSystem = ActorSystem.create("custerA", config); return actorSystem } fun startShardRegion(port: Int) { var actorSystem = createActorSystem(port) val settings = ClusterShardingSettings.create(actorSystem)//.withRole("ClusterShardRole") val shardReg = ClusterSharding.get(actorSystem).start(
"dogShard",
Props.create(DogActor::class.java),
settings,
ShardExtractor(),
ShardCoordinator.LeastShardAllocationStrategy(10, 1),
handOffStopMessage
) for (i in 1..10) { shardReg.tell(DogMsg(i, " wang"), ActorRef.noSender()) Thread.sleep(3000)
} } fun shardRegProxy() { var actorSystem = createActorSystem(2663) //startProxy 代理模式,即它不会承载任何实体本身,但知道如何将消息委托到正确的位置
ClusterSharding.get(actorSystem)
.startProxy("dogShard", Optional.empty(), ShardExtractor())
.let { println(" shard proxy $it started.") } Thread.sleep(3000) var shardReg = ClusterSharding.get(actorSystem).shardRegion("dogShard") for (i in 1..100) { shardReg.tell(DogMsg(i, "C wang"), ActorRef.noSender()) Thread.sleep(1500)
}
}

再分别启动入口

fun main() {
startShardRegion(2661)
}
fun main() {
startShardRegion(2662)
}
fun main() {

    shardRegProxy()

}

配置文件:

akka {
actor {
provider = "cluster"
} # For the sample, just bind to loopback and do not allow access from the network
# the port is overridden by the logic in main class
remote.artery {
enabled = on
transport = tcp
canonical.port = 0
canonical.hostname = 127.0.0.1
} cluster {
seed-nodes = [
"akka://custerA@127.0.0.1:2661",
"akka://custerA@127.0.0.1:2662"] # auto downing is NOT safe for production deployments.
# you may want to use it during development, read more about it in the docs.
auto-down-unreachable-after = 10s
}
}

注意

以上示例需在同属一个集群,消息才能正常中转,所以一定要保障 ActorSystem.create(name,config) name 为一致!(调了半天消息一直没有发送成功,原来是这里的问题,KAO!)

同一个集群同一个ActorSystem name!

不然会报异常:

No coordinator found to register. Probably, no seed-nodes configured and manual cluster join not performed

akka 集群分片的更多相关文章

  1. Akka(13): 分布式运算:Cluster-Sharding-运算的集群分片

    通过上篇关于Cluster-Singleton的介绍,我们了解了Akka为分布式程序提供的编程支持:基于消息驱动的运算模式特别适合分布式程序编程,我们不需要特别的努力,只需要按照普通的Actor编程方 ...

  2. Akka Cluster之集群分片

    一.介绍  当您需要在集群中的多个节点之间分配Actor,并希望能够使用其逻辑标识符与它们进行交互时,集群分片是非常有用的.你无需关心Actor在集群中的物理位置,因为这可能也会随着时间的推移而发生变 ...

  3. Akka-Cluster(6)- Cluster-Sharding:集群分片,分布式交互程序核心方式

    在前面几篇讨论里我们介绍了在集群环境里的一些编程模式.分布式数据结构及具体实现方式.到目前为止,我们已经实现了把程序任务分配给处于很多服务器上的actor,能够最大程度的利用整体系统的硬件资源.这是因 ...

  4. akka-typed(7) - cluster:sharding, 集群分片

    在使用akka-typed的过程中发现有很多地方都简化了不少,变得更方便了,包括:Supervision,只要用Behaviors.supervise()把Behavior包住,很容易就可以实现这个a ...

  5. mongodb集群+分片部署(二)

    机器:10.165.38.68    10.165.38.72 部署包:mongodb-linux-x86_64-rhel55-3.0.2.tgz(百度云盘下载地址:http://pan.baidu. ...

  6. AKKA 集群中的发布与订阅Distributed Publish Subscribe in Cluster

    Distributed Publish Subscribe in Cluster 基本定义 在单机环境下订阅与发布是很常用的,然而在集群环境是比较麻烦和不好实现的: AKKA已经提供了相应的实现,集群 ...

  7. Akka系列(十):Akka集群之Akka Cluster

    前言........... 上一篇文章我们讲了Akka Remote,理解了Akka中的远程通信,其实Akka Cluster可以看成Akka Remote的扩展,由原来的两点变成由多点组成的通信网络 ...

  8. 搭建高可用mongodb集群—— 分片

    从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出 ...

  9. mongodb 集群分片

    分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...

随机推荐

  1. 【Linux】PuTTY----------windows访问Linux 快捷方便

    第一步:百度PuTTY,下载好后直接运行,界面如下: 第二步:后输入IP:10.45.XX.XX,直接点击open按钮 第三步:输入用户名: 第四步:密码~ 现在,您就可以对你访问的linux设备进行 ...

  2. js操作select控件大全(包含新增、修改、删除、选中、清空、判断存在等)

    原文:js操作select控件大全(包含新增.修改.删除.选中.清空.判断存在等) js操作select控件大全(包含新增.修改.删除.选中.清空.判断存在等) js 代码// 1.判断select选 ...

  3. LINQ查询表达式---------where子句

    LINQ查询表达式---------where子句 where 子句用在查询表达式中,用于指定将在查询表达式中返回数据源中的哪些元素. 它将一个布尔条件(“谓词”)应用于每个源元素(由范围变量引用), ...

  4. PHP trait 特性在 Laravel 中的使用个人心得

    trait 是在PHP5.4中为了方便代码复用的一种实现方式,但目前我在看的的PHP项目中较少看的有程序员去主动使用这个实现方式,在laravel中有很多 trait 的使用,关于trait 在 la ...

  5. 【Windows10 IoT开发系列】配置篇

    原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry ...

  6. 理解typedef(转)

    // 从别人那转的,调整下格式便于阅读. 首先请看看下面这两句: typedef ]; typedef void (*p)(void); 如果你能一眼就看出它们的意思,那请不要再往下看了.如果你不太理 ...

  7. Setting up multi nodes live migration in Openstack Juno with devstack

    Setting up multi nodes live migration in Openstack Juno with devstack Summary Live migration overvie ...

  8. RoboVM 1.1 发布,Java 转原生平台代码

    分享 <关于我> 分享  [中文纪录片]互联网时代                 http://pan.baidu.com/s/1qWkJfcS 分享 <HTML开发MacOSAp ...

  9. Realm_King 之 .NET操作XML完整类

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;u ...

  10. linux 磁盘控件找到大文件

    df -lh Used:已经使用的空间 Avail:可以使用的空间 Mounted on:挂载的目录 然后找到大文件 du是linux下用看查看磁盘的命令 下面我们先一个目录的来查看空间占用情况 du ...