AKKA Router路由

路由概念

大量的actor在并行工作的时候,处理到来的消息流,这时候就需要一个组件或者东西来引导消息从源到目的地Actor,这个组件或者东西就是Router
在Akka中,router也是一种actor 类型,它路由到来的消息到其他的actors,其他那些actors就叫做routees(被路由对象)


Routing模式由Router和Routee组成:
Routee是负责具体运算的Actor
Router 是把外界发来消息按照某种指定的方式(默认提供了多种路由逻辑类)分配给Routee去运算,用于调度actor任务或进行负载均衡策略

 

Pool 和 Group模式


Router又可分Pool和Group两种模式:
Router-Pool模式中Router负责构建所有的Routee。路由器创建routee作为子actor,并在该子actor终止时将它从路由器中移除。

Router-Group模式中的Routees由外界其它Actor产生(自行创建,自行管理),特点是能实现灵活的Routee构建和监控

 

路由逻辑类

akka.routing.RoundRobinRoutingLogic  轮询
akka.routing.RandomRoutingLogic  随机
akka.routing.SmallestMailboxRoutingLogic 空闲
akka.routing.BroadcastRoutingLogic 广播
akka.routing.ScatterGatherFirstCompletedRoutingLogic
akka.routing.TailChoppingRoutingLogic
akka.routing.ConsistentHashingRoutingLogic

 

实现示例:

 

package router

import akka.actor.AbstractActor
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.japi.pf.ReceiveBuilder
import akka.routing.*
import org.slf4j.LoggerFactory

/**
 * Created by: tankx
 * Date: 2019/7/20
 * Description: 路由示例
 */
class WorkActor : AbstractActor() {
  var log = LoggerFactory.getLogger(WorkActor::class.java)

  override fun createReceive(): Receive {
    return ReceiveBuilder.create().matchAny(this::receive).build()
  }


  fun receive(msg: Any) {
    log.info(" {}: $msg", self.path())
  }
}

class RouterActor : AbstractActor() {

  var log = LoggerFactory.getLogger(RouterActor::class.java)

  private lateinit var router: Router;

  override fun preStart() {
    super.preStart()
    var list = arrayListOf<Routee>()

    for (i in 1..10) {
      var worker = context.actorOf(Props.create(WorkActor::class.java), "worker_$i")
      list.add(ActorRefRoutee(worker))
    }

    /**
     * 路由方式
     * RoundRobinRoutingLogic: 轮询
     * BroadcastRoutingLogic: 广播
     * RandomRoutingLogic: 随机
     * SmallestMailboxRoutingLogic: 空闲
     */
    router = Router(RoundRobinRoutingLogic(), list)

  }

  override fun createReceive(): Receive {
    return ReceiveBuilder.create().matchAny(this::receive).build()
  }


  fun receive(msg: Any) {
    //log.info("RouterActor : $msg")
    router.route(msg, sender)
  }

}

fun main() {

  var actorSystem = ActorSystem.create("RouterSystem")

  var routerActor = actorSystem.actorOf(Props.create(RouterActor::class.java))



  for (i in 1..20) {

    Thread.sleep(2000)

    routerActor.tell("消息来了", ActorRef.noSender())
  }

}

 

指定path模式,远程调用(集群内部访问)

package router.cluster

import akka.actor.AbstractActor
import akka.actor.Props
import akka.japi.pf.ReceiveBuilder
import org.slf4j.LoggerFactory
import router.WorkActor

/**
 * Created by: tankx
 * Date: 2019/7/20
 * Description:
 */
class WorkActor : AbstractActor() {
  var log = LoggerFactory.getLogger(WorkActor::class.java)

  override fun createReceive(): Receive {
    return ReceiveBuilder.create().matchAny(this::receive).build()
  }


  fun receive(msg: Any) {
    log.info(" {}: $msg", self.path())
  }

}

 

package router.cluster

import akka.actor.*
import akka.japi.pf.ReceiveBuilder
import org.slf4j.LoggerFactory
import router.WorkActor
import akka.remote.routing.RemoteRouterConfig
import akka.routing.BroadcastGroup
import akka.routing.BroadcastPool
import akka.routing.FromConfig
import akka.routing.RoundRobinPool
import com.typesafe.config.ConfigFactory


/**
 * Created by: tankx
 * Date: 2019/7/20
 * Description:
 */
class MyService : AbstractActor() {

  var log = LoggerFactory.getLogger(MyService::class.java)

  override fun createReceive(): Receive {
    return ReceiveBuilder.create().matchAny(this::receive).build()
  }


  fun receive(msg: Any) {
    log.info(" {}: $msg", self.path())
  }

}


fun getActorSystem(port: Int): ActorSystem {

  val config = ConfigFactory.parseString(
    "akka.remote.netty.tcp.port=$port"
  ).withFallback(
    ConfigFactory.load("application_router.conf")
  )

  var actorSystem = ActorSystem.create("RouterSystem", config);


  return actorSystem
}
//读取配置文件方式
fun loadRouterByConfig() {

  val actorSystem = getActorSystem(3662);

  var router = actorSystem.actorOf(FromConfig.getInstance().props(), "workerRouter")

  for (i in 1..10) {
    router.tell("test", ActorRef.noSender())
    Thread.sleep(2000)
  }
}
//代码方式
fun loadRouterByCode() {

  val actorSystem = getActorSystem(3662);

  var address = listOf<Address>(
    AddressFromURIString.parse("akka.tcp://RouterSystem@127.0.0.1:2663"),
    AddressFromURIString.parse("akka.tcp://RouterSystem@127.0.0.1:2661")
  )
  //var paths = listOf("/user/MyWorker")//可以配置多个地址 akka://RouterSystem/user/MyWorker

  var router = actorSystem.actorOf(
    RemoteRouterConfig(
      BroadcastPool(2),
      address
    ).props(Props.create(router.cluster.WorkActor::class.java)), "workerRouter"
  )


  for (i in 1..20) {
    router.tell("test", ActorRef.noSender())
    Thread.sleep(2000)
  }
}


fun main() {
  //loadRouterByCode()

  loadRouterByConfig()

}

配置文件

akka {
  actor {
    provider = "cluster"
  }

  remote {
    //log-remote-lifecycle-events = off
    netty.tcp {
      hostname = "127.0.0.1"
      port = 2661
    }
  }

  # 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 = 2661
  //    canonical.hostname = 127.0.0.1
  //  }

  cluster {
    seed-nodes = [
      "akka.tcp://RouterSystem@127.0.0.1:2661"
    ]

    # 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
  }
}

 

分不同JVM启动

fun main() {

  var actorSystem = getActorSystem(2661)
  var workActor = actorSystem.actorOf(Props.create(WorkActor::class.java), "MyWorker")

}

 

fun main() {

  var actorSystem = getActorSystem(2663)
  var workActor = actorSystem.actorOf(Props.create(WorkActor::class.java), "MyWorker")


}

 

结果调用输出

2019-07-22 12:25:42.589 [RouterSystem-akka.actor.default-dispatcher-21] INFO  router.WorkActor -  akka://RouterSystem/remote/akka.tcp/RouterSystem@127.0.0.1:3662/user/workerRouter/c2: test
2019-07-22 12:25:44.589 [RouterSystem-akka.actor.default-dispatcher-2] INFO  router.WorkActor -  akka://RouterSystem/remote/akka.tcp/RouterSystem@127.0.0.1:3662/user/workerRouter/c2: test
2019-07-22 12:25:46.590 [RouterSystem-akka.actor.default-dispatcher-2] INFO  router.WorkActor -  akka://RouterSystem/remote/akka.tcp/RouterSystem@127.0.0.1:3662/user/workerRouter/c2: test

 

通过以上示例基本可以了解AKK的路由模式与应用了。

 

posted @ 2019-07-22 13:04  itank  阅读(1734)  评论(0编辑  收藏  举报