- 项目实战:利用Akka的Actor编程模型,实现2个进程间的通信
 架构图:
- Master、Master Actor <======通过RPC相互通信======> Worker、Worker Actor
 
重要类介绍
ActorSystem:在Akka中,ActorSystem是一个重量级的结构,他需要分配多个线程,所以在实际应用中,ActorSystem通常是一个单例对象,我们可以使用这个ActorSystem创建很多Actor。
注意:- 1、ActorSystem是一个进程中的老大,它负责创建和监督actor
 - 2、ActorSystem是一个单例对象
 - 3、actor负责通信
 
Actor:在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法。
- 1、preStart()方法:该方法在Actor对象构造方法执行后执行,整个Actor生命周期中仅执行一次。
 - 2、receive()方法:该方法在Actor的preStart方法执行完成后执行,用于接收消息,会被反复执行。
 
- 具体代码:
Master类: 
package cn.akka.rpc
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
//todo:利用akka中的actor模型,实现两个进程之间的通信------Master端
class Master extends Actor {
  println("====== Master constructor invoked ======")
  //todo:它会在构造代码块之后被调用,并且只会被执行一次
  override def preStart(): Unit = {
    println("====== preStart method invoked =======")
  }
  //todo:它会在preStart方法执行后被调用,并且是一直循环被执行
  override def receive: Receive = {
    case "connect" => {
      println("====== a client connected ======")
      sender ! "success"
    }
  }
}
object Master {
  def main(args: Array[String]): Unit = {
    //todo:定义master的IP地址
    val host = args(0)
    //todo:定义master的port端口
    val port = args(1)
    //todo:准备配置文件信息
    val configStr =
      s"""
        |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
        |akka.remote.netty.tcp.hostname = "$host"
        |akka.remote.netty.tcp.port = "$port"
      """.stripMargin
    //todo:利用ConfigFactory解析字符串,获取对应的配置
    val config = ConfigFactory.parseString(configStr)
    //todo:1.创建ActorSystem,它是整个进程的老大,负责创建和监督actor,它是单例对象
    val masterActorSystem: ActorSystem = ActorSystem("masterActorSystem", config)
    //todo:2.ActorSystem创建actor
    val masterActor: ActorRef = masterActorSystem.actorOf(Props(new Master), "masterActor")
    //todo:3.向master actor发送消息
    //masterActor ! "connect"
  }
}
Worker类:
package cn.akka.rpc
import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
//todo:利用akka中的actor模型,实现两个进程之间的通信------Worker端
class Worker extends Actor {
  println("====== Worker constructor invoked ======")
  override def preStart(): Unit = {
    println("====== preStart method invoked ======")
    //todo:1.拿到 master actor 的引用
    //todo:2.AcotorContext上下文对象调用actorSelection
    //todo:3.需要:通信协议、master的ip地址、master的端口、master对应的ActorSystem,actor层级
    val master: ActorSelection = context.actorSelection("akka.tcp://masterActorSystem@192.168.106.26:8888/user/masterActor")
    //todo:4.向master发送消息
    master ! "connect"
  }
  override def receive: Receive = {
    case "connect" => {
      println("====== a client connected ======")
    }
    case "success" => {
      println("====== 我已经注册成功!!! ======")
    }
  }
}
object Worker {
  def main(args: Array[String]): Unit = {
    //todo:worker的IP地址
    val host = args(0)
    //todo:worker的端口
    val port = args(1)
    //todo:准备配置信息
    val configStr =
      s"""
        |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
        |akka.remote.netty.tcp.hostname = "$host"
        |akka.remote.netty.tcp.port = "$port"
      """.stripMargin
    //todo:利用ConfigActor解析字符串配置信息
    val config = ConfigFactory.parseString(configStr)
    //todo:1.创建ActorSystem对象,它是整个进程的老大,负责创建和监督actor,它是单例对象
    val workerActorSystem: ActorSystem = ActorSystem("workerActorSystem", config)
    //todo:2.利用workerActorSystem创建Worker的actor
    val workerActor: ActorRef = workerActorSystem.actorOf(Props(new Worker), "workerActor")
    //todo:3.向workerActor发送消息
    workerActor ! "connect"
  }
}
- 运行结果:
 
Master:
====== Master constructor invoked ======
====== preStart method invoked =======
====== a client connected ======Worker:
====== Worker constructor invoked ======
====== preStart method invoked ======
====== a client connected ======
====== 我已经注册成功!!! ======每一个成功的背后都有无数个无人知晓的黑夜。
因为
夜晚,是超越对手的最佳时机。
===================== 码农1024 =====================#蔺光岭#

还不快抢沙发