akka 集群分片
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 集群分片的更多相关文章
- Akka(13): 分布式运算:Cluster-Sharding-运算的集群分片
通过上篇关于Cluster-Singleton的介绍,我们了解了Akka为分布式程序提供的编程支持:基于消息驱动的运算模式特别适合分布式程序编程,我们不需要特别的努力,只需要按照普通的Actor编程方 ...
- Akka Cluster之集群分片
一.介绍 当您需要在集群中的多个节点之间分配Actor,并希望能够使用其逻辑标识符与它们进行交互时,集群分片是非常有用的.你无需关心Actor在集群中的物理位置,因为这可能也会随着时间的推移而发生变 ...
- Akka-Cluster(6)- Cluster-Sharding:集群分片,分布式交互程序核心方式
在前面几篇讨论里我们介绍了在集群环境里的一些编程模式.分布式数据结构及具体实现方式.到目前为止,我们已经实现了把程序任务分配给处于很多服务器上的actor,能够最大程度的利用整体系统的硬件资源.这是因 ...
- akka-typed(7) - cluster:sharding, 集群分片
在使用akka-typed的过程中发现有很多地方都简化了不少,变得更方便了,包括:Supervision,只要用Behaviors.supervise()把Behavior包住,很容易就可以实现这个a ...
- mongodb集群+分片部署(二)
机器:10.165.38.68 10.165.38.72 部署包:mongodb-linux-x86_64-rhel55-3.0.2.tgz(百度云盘下载地址:http://pan.baidu. ...
- AKKA 集群中的发布与订阅Distributed Publish Subscribe in Cluster
Distributed Publish Subscribe in Cluster 基本定义 在单机环境下订阅与发布是很常用的,然而在集群环境是比较麻烦和不好实现的: AKKA已经提供了相应的实现,集群 ...
- Akka系列(十):Akka集群之Akka Cluster
前言........... 上一篇文章我们讲了Akka Remote,理解了Akka中的远程通信,其实Akka Cluster可以看成Akka Remote的扩展,由原来的两点变成由多点组成的通信网络 ...
- 搭建高可用mongodb集群—— 分片
从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出 ...
- mongodb 集群分片
分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...
随机推荐
- QML中文件的加载(三种方法)
在这里小小总结一下QML文件中如何加载QML文件与JavaScript文件. 1.QML文件中加载JavaScript文件 语法: import <ModuleIdentifier> &l ...
- fileapi.h里的API函数(包括LockFileEx和FindFirstChangeNotification函数)
/** * This file is part of the mingw-w64 runtime package. * No warranty is given; refer to the file ...
- Upgrade a Non-CDB To a PDB on CDB
.Stop the cluster database and start database on one node with read noly [oracle@raca1 admin]$ srvct ...
- asp.net mvc实现微信外H5支付方法
一.微信支付方式介绍 微信提供了各种支付方式,试用于各种不同的支付场景,主要有如下几种: 1.刷卡支付 刷卡支付是用户展示微信钱包内的“刷卡条码/二维码”给商户系统扫描后直接完成支付的模式.主要应用线 ...
- 第一个SpringBoot测试实例
1.SpringBoot项目构建:http://start-spring.io 自动化构建SpringBoot项目,保存在本地并解压 2.安装gradle并配置gradle环境 3.配置阿里云ma ...
- Dynamics 365中的事件框架与事件执行管道(Event execution pipeline)
本文介绍了Microsoft Dynamics 365(以下简称D365)中的两个概念,事件框架(Event Framework)与事件执行管道(Event execution pipeline). ...
- MYSQL的全局变量和会话变量
系统变量又分为全局变量与会话变量. 全局变量在MYSQL启动的时候由服务器自动将它们初始化为默认值,这些默认值可以通过更改my.ini这个文件来更改. 会话变量在每次建立一个新的连接的时候,由MYSQ ...
- vue路由传参query和params的区别(详解!)
1.query使用path和name传参都可以,而params只能使用name传参. query传参: 页面: this.$router.push({ path:'/city',name:'City' ...
- 视频直播:Windows中各类画面源的截取和合成方法总结
当今,视频直播技术和实时音视频技术已经是很多行业必备,典型的应用场景有教育直播.远程视频会议.互联网娱乐等.在移动端发起直播,其画面源的种类是十分有限的,无非是取摄像头.截屏等.PC端由于其系统资源充 ...
- Storm 学习之路(七)—— Storm集成 Redis 详解
一.简介 Storm-Redis提供了Storm与Redis的集成支持,你只需要引入对应的依赖即可使用: <dependency> <groupId>org.apache.st ...