Akka笔记–演员信息–请求和回应– 3

上次看到Actor消息时,我们看到了发送fire-n-forget消息的方式(意思是,我们只是向Actor发送消息,但不希望Actor做出响应)。

从技术上讲,我们始终向其发送有关其副作用的消息。 这是设计使然。 除了不响应之外,目标Actor还可通过该消息执行以下操作:

  1. 将回复发送回发件人(在我们的示例中, TeacherActor会以引号回复给StudentActor
  2. 将响应转发回其他可能是目标受众的Actor,而后者又可能会做出响应/转发/有副作用。 路由器和管理程序就是这些情况的示例(我们将很快对其进行介绍)。

要求与回应

在本文中,我们将仅关注点1-请求-响应周期。

Akka笔记–演员信息–请求和回应– 3_第1张图片

图片传达了我们这次要实现的目标。 为了简洁起见,我没有在图片中表示ActorSystem,Dispatcher或Mailboxes。

  1. DriverAppInitSignal消息发送给StudentActor
  2. 所述StudentActor反作用于InitSignal消息并发送QuoteRequest消息给TeacherActor
  3. 就像我们在第一次讨论中看到的那样, TeacherActorQuoteResponse 进行响应。
  4. StudentActor只需将QuoteResponse记录到控制台/记录器。

我们还将准备一个测试用例进行验证。

现在让我们详细看一下这4点:

1.

Akka笔记–演员信息–请求和回应– 3_第2张图片

到现在DriverApp ,您可能已经猜出了DriverApp做什么。 只需四件事:

  1. 初始化ActorSystem
  2. //Initialize the ActorSystem
      val system = ActorSystem("UniversityMessageSystem")
  3. 创建TeacherActor
  4. //create the teacher actor
      val teacherRef = system.actorOf(Props[TeacherActor], "teacherActor")
  5. 创建StudentActor
  6. //create the Student Actor - pass the teacher actorref as a constructor parameter to StudentActor
      val studentRef = system.actorOf(Props(new StudentActor(teacherRef)), "studentActor")

    您会注意到,我将TeacherActorActorRef传递给StudentActor的构造函数,以便StudentActor可以使用ActorRef将消息发送给TeacherActor。 还有其他方法可以实现此目的(例如传递Props ),但是当我们在以下文章中介绍Supervisor和Routers时,此方法将派上用场。 我们也将很快着眼于儿童演员,但这在语义上不是正确的方法–学生创建老师听起来并不好。 可以?

    最后,

  7. DriverApp然后将发送InitSignalStudentActor ,使StudentActor可以开始发送QuoteRequest消息给TeacherActor。
//send a message to the Student Actor
  studentRef ! InitSignal

差不多就是DriverClass。 在最终关闭ActorSystem之前, Thread.sleepActorSystem.shutdown只是要等待几秒钟,以便消息发送完成。

DriverApp.scala

package me.rerun.akkanotes.messaging.requestresponse

import akka.actor.ActorSystem  
import akka.actor.Props  
import me.rerun.akkanotes.messaging.protocols.StudentProtocol._  
import akka.actor.ActorRef

object DriverApp extends App {

  //Initialize the ActorSystem
  val system = ActorSystem("UniversityMessageSystem")

  //construct the teacher actor
  val teacherRef = system.actorOf(Props[TeacherActor], "teacherActor")

  //construct the Student Actor - pass the teacher actorref as a constructor parameter to StudentActor
  val studentRef = system.actorOf(Props(new StudentActor(teacherRef)), "studentActor")

  //send a message to the Student Actor
  studentRef ! InitSignal

  //Let's wait for a couple of seconds before we shut down the system
  Thread.sleep(2000)

  //Shut down the ActorSystem. 
  system.shutdown()

}

2.

4.

我为什么要结合第2点和第4点? 因为它是如此简单,如果我分开它们,您会恨我。

Akka笔记–演员信息–请求和回应– 3_第3张图片

所以,点2 -的StudentActor接收InitSignal从消息DriverApp并发送QuoteRequest到TeacherActor。

def receive = {  
    case InitSignal=> {
          teacherActorRef!QuoteRequest
    }
    ...
    ...

而已 !!!

第4点– StudentActor记录了它从TeacherActor收到的消息。

Akka笔记–演员信息–请求和回应– 3_第4张图片

只是,如承诺的那样:

case QuoteResponse(quoteString) => {  
      log.info ("Received QuoteResponse from Teacher")
      log.info(s"Printing from Student Actor $quoteString")
}

我相信您会同意,现在它看起来几乎像是伪代码。

因此,整个StudentActor类如下:

学生演员

package me.rerun.akkanotes.messaging.requestresponse

import akka.actor.Actor  
import akka.actor.ActorLogging  
import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._  
import me.rerun.akkanotes.messaging.protocols.StudentProtocol._  
import akka.actor.Props  
import akka.actor.ActorRef

class StudentActor (teacherActorRef:ActorRef) extends Actor with ActorLogging {

  def receive = {
    case InitSignal=> {
      teacherActorRef!QuoteRequest
    }

    case QuoteResponse(quoteString) => {
      log.info ("Received QuoteResponse from Teacher")
      log.info(s"Printing from Student Actor $quoteString")
    }
  }
}

3.

这与我们在fire-n-forget写作中所看到的完全相同的代码。

TeacherActor收到QuoteRequest消息,然后将QuoteResponse发送回去。

教师演员

package me.rerun.akkanotes.messaging.requestresponse

import scala.util.Random

import akka.actor.Actor  
import akka.actor.ActorLogging  
import akka.actor.actorRef2Scala  
import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._


class TeacherActor extends Actor with ActorLogging {

  val quotes = List(
    "Moderation is for cowards",
    "Anything worth doing is worth overdoing",
    "The trouble is you think you have time",
    "You never gonna know if you never even try")

  def receive = {

    case QuoteRequest => {

      import util.Random

      //Get a random Quote from the list and construct a response
      val quoteResponse = QuoteResponse(quotes(Random.nextInt(quotes.size)))

      //respond back to the Student who is the original sender of QuoteRequest
      sender ! quoteResponse

    }
  }
}

测试用例

现在,我们的测试用例将模拟DriverApp 由于StudentActor仅记录了消息,而我们无法对QuoteResponse本身进行断言,因此我们仅断言EventStream中是否存在日志消息(就像我们上次讨论的那样)。

因此,我们的测试用例看起来像:

"A student" must {

    "log a QuoteResponse eventually when an InitSignal is sent to it" in {

      import me.rerun.akkanotes.messaging.protocols.StudentProtocol._

      val teacherRef = system.actorOf(Props[TeacherActor], "teacherActor")
      val studentRef = system.actorOf(Props(new StudentActor(teacherRef)), "studentActor")

      EventFilter.info (start="Printing from Student Actor", occurrences=1).intercept{
        studentRef!InitSignal
      }
    }
  }

整个项目可以从github此处下载。

接下来,我们将看到如何在Akka中使用调度程序,以及如何使用Kamon监视Akka应用程序。

翻译自: https://www.javacodegeeks.com/2014/10/akka-notes-actor-messaging-request-and-response-3.html

你可能感兴趣的:(Akka笔记–演员信息–请求和回应– 3)