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. ARTS 1.21 - 1.25

    每周一个 Algorithm,Review 一篇英文文章,总结一个工作中的技术 Tip,以及 Share 一个传递价值观的东西! Algorithm: 学习算法 题目:3Sum Closest 解题过 ...

  2. BSTR使用误区以及隐藏的内存破坏和内存泄漏

    BSTR使用误区以及隐藏的内存破坏和内存泄漏 作者:magictong 简介 BSTR的数据结构是什么样子并不是本文讨论的问题,但是却是本文的基础.在解决COM的跨平台编程的问题时,需要定义一种通用的 ...

  3. DIOCP3 DEMO的编译(去掉VCL前缀)

    总有些朋友问我,关于DEMO编译的一些问题,每次都回答大概都差不多,我想还是写篇说明书给大家,关于DEMO编译的步骤. [环境设定] 1.将DIOCP3\source路径添加到Delphi的搜索路径, ...

  4. Oracle数据库密码重置、导入导出库命令

    重置办法如下:打开CMD命令提示符,然后输入下面命令进行重置: 输入sqlplus /nolog,回车 SQL> conn /as sysdba 已连接: SQL>alter user s ...

  5. VS 查看是否有内存泄露的方法

    加入下列宏定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #else #defi ...

  6. baiduMap试手《办理进京证和市区警察查询进京证的地址浏览》

    没用过baidu的map api其实挺简单,申请一个key,然后根据坐标在地图上生成对象,看了官方的dome多少知道有些什么功能了,没什么可说的直接贴效果. <!DOCTYPE html> ...

  7. Win7 访问 数据库 慢

    不让TCP/IP调谐拖累网速 在Windows Server 2008工作环境中,下载访问网络中大容量的文件内容时,我们有时会感觉到网络连接速度非常缓慢,严重的时候还会出现不能访问的现象.遭遇这类故障 ...

  8. vue.js与后台模板引擎“双花括号”冲突时的解决办法

    后台渲染模板如swig,也使用“{{ }}“作为渲染,与前端vue的产生冲突,此时只要在新建Vue对象时,添加delimiters: ['${', '}'],就搞定了,代码如下 <!DOCTYP ...

  9. Java打印实心、空心的三角形和菱形

    1.实心三角形 代码: import java.util.Scanner; public class Test { public static void main(String[] args) { i ...

  10. 解决wireshark打开错误

    错误提示如下: Lua: Error during loading: [string "/usr/share/wireshark/init.lua"]:44: dofile has ...