2016-05-30 2 views
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 
    } 
    } 
} 

Несколько вопросов:

  1. Почему бэкэнд подписывается на кластере, а интерфейс отсутствует?
  2. Итак, является ли интерфейс на самом деле членом кластера?
  3. Номер порта backend предоставляется один раз в application.conf, и еще раз в методе initiate, почему?

ответ

2
  1. Похоже, в этом примере мы хотим бэкэнд (рабочие), чтобы открыть внешний интерфейс (мастер) и зарегистрировать себя вместо того, чтобы позволить интерфейс для прослушивания событий кластера, так что это вопрос дизайна, я думаю.
  2. Frontend является членом кластера, он просто не подписан на событий кластера.
  3. Фронтальный ввод инициализирован настройками из приложения.conf, а также начальным узлом, в то время как у серверов есть порт 0 в application.conf, что означает, что они будут инициализированы случайным портом, если вы не переопределяете его программно, как в методе initiate ,
Смежные вопросы