0
Вот код:Разница между интерфейсом и бэкэндом в кластере akka?
// Backend.scala
package com.packt.akka.cluster
import akka.actor.{Actor, ActorSystem, Props, RootActorPath}
import akka.cluster.ClusterEvent.MemberUp
import akka.cluster._
import com.packt.akka.commons._
import com.typesafe.config.ConfigFactory
class Backend extends Actor {
val cluster = Cluster(context.system)
// subscribe to cluster changes, MemberUp
// re-subscribe when restart
override def preStart(): Unit = {
cluster.subscribe(self, classOf[MemberUp])
}
override def postStop(): Unit = {
cluster.unsubscribe(self)
}
def receive = {
case Add(num1, num2) =>
println(s"I'm a backend with path: ${self} and I received add operation.")
println(s"Result is ${num1 + num2}")
case MemberUp(member) =>
if(member.hasRole("frontend")){
context.actorSelection(RootActorPath(member.address)/"user"/"frontend") ! BackendRegistration
}
}
}
object Backend {
def initiate(port: Int = 8991): Unit = {
val config = ConfigFactory.parseString(s"akka.remote.netty.tcp.port=$port").
withFallback(ConfigFactory.load().getConfig("Backend"))
val system = ActorSystem("ClusterSystem", config)
val Backend = system.actorOf(Props[Backend], name = "Backend")
}
}
// ClusterApp.scala
package com.packt.akka.cluster
import akka.cluster._
import com.packt.akka.commons._
import akka.actor.{ Actor, ActorRef, ActorSystem, Props }
object ClusterApp extends App {
//initiate frontend node
Frontend.initiate()
//initiate three nodes from backend
Backend.initiate(2552)
Backend.initiate(2560)
Backend.initiate(2561)
Thread.sleep(10000)
Frontend.getFrontend ! Add(2, 4)
Frontend.getFrontend ! Add(2, 5)
Frontend.getFrontend ! Add(2, 6)
}
// Frontend.scala
package com.packt.akka.cluster
import akka.actor.{Actor, ActorRef, ActorSystem, Props, Terminated}
import com.packt.akka.commons._
import com.typesafe.config.ConfigFactory
import scala.util.Random
class Frontend extends Actor {
var backends = IndexedSeq.empty[ActorRef]
def receive = {
case Add if backends.isEmpty =>
println("Service unavailable, cluster doesn't have backend node.")
case addOp: Add =>
println("Frontend: I'll forward add operation to backend node to handle it.")
backends(Random.nextInt(backends.size)) ! addOp
case BackendRegistration if !(backends.contains(sender())) =>
backends = backends :+ sender()
context watch (sender())
case Terminated(a) =>
backends = backends.filterNot(_ == a)
}
}
object Frontend {
private var _frontend: ActorRef = _
def initiate() = {
val config = ConfigFactory.load().getConfig("Frontend")
val system = ActorSystem("ClusterSystem", config)
_frontend = system.actorOf(Props[Frontend], name = "frontend")
}
def getFrontend = _frontend
}
// application.conf
Frontend {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2551
}
}
cluster {
roles = ["frontend"]
seed-nodes = [
"akka.tcp://[email protected]:2551"]
auto-down-unreachable-after = 10s
}
}
}
Backend {
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 0
}
}
cluster {
roles = ["backend"]
seed-nodes = [
"akka.tcp://[email protected]:2551"]
auto-down-unreachable-after = 10s
}
}
}
Несколько вопросов:
- Почему бэкэнд подписывается на кластере, а интерфейс отсутствует?
- Итак, является ли интерфейс на самом деле членом кластера?
- Номер порта backend предоставляется один раз в application.conf, и еще раз в методе initiate, почему?