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. Qt官方对OpenSSL的编译方法的描述,单独下载的Qt library则一般不带SSL(包括QT FAQ)

    https://wiki.qt.io/MSYS2http://wiki.qt.io/Compiling_OpenSSL_with_MinGWhttps://wiki.qt.io/MinGW-64-bi ...

  2. ubuntu Linux 操作系统安装与配置

    Ubuntu是一个以桌面应用为主的Linux操作系统.Ubuntu每六个月发布一个新版本(一般是4和10月份,命名为YY.MM),每一个普通版本都将被支持 18个月,长期支持版(Long Term S ...

  3. SQLSERVER 数据库备份脚本-支持多库备份

    原文:SQLSERVER 数据库备份脚本-支持多库备份 <pre name="code" class="sql">--变量定义 DECLARE @b ...

  4. 通过HTTP Header控制缓存

    我们经常通过缓存技术来加快网站的访问速度,从而提升用户体验.HTTP协议中也规定了一些和缓存相关的Header,来允许浏览器或共享高速缓存缓存资源.这些Header包括: Last-Modified ...

  5. C++/CLI 中使用 ref 和 out

    void fun(int^ % i){} // C# ref void fun([out]int^ % i) {} // C# out

  6. WPF使用AForge实现Webcam预览(一)

    本文简略地介绍一下如果使用AForge来实现前置/后置摄像头的预览功能. 要使用AForge,就需要添加AForge NuGet相关包的引用,这些包依赖的其他包会自动安装. AForge.Contro ...

  7. 静态编译 Qt 5.6

    源码下载 Qt git地址:git://code.qt.io/qt/qt5.git 推荐用 SourceTree 客户端来克隆源码 准备工作 系统 Windows 7 或者 Windows 10 编译 ...

  8. Qt之QSS(QTreeView)

    check 是选中 前面的指示器的状态 select 是选中 项目 item 的状态. http://blog.csdn.net/u011012932/article/details/52606662

  9. 浅析C#代理

    delegate 是委托声明的基础,是.net 的委托的声明的关键字action 是基于delegate实现的代理 有多个参数(无限制个数)无返回值的代理 func 是基于delegate实现的代理 ...

  10. C语言实现常用排序算法——基数排序

    #include<stdio.h> #include<math.h> #define SIZE 10 #define C_SIZE 20 /*行数稳定=10,切记!列数务必搞的 ...