前面我们讲到了Actor的
消息传递,并看到了如何发送一条fire-n-forget消息(也就是说,消息发送给Actor后我们就不管了,不从Actor那接收响应)。
技术上来讲,消息发送给Actor就是希望能有副作用的。设计上便是如此。目标Actor可以不做响应,也可以做如下两件事情——
1. 给发送方回复一条响应(在本例中,TeacherActor会将一句名言回复给StudentActor)
2. 将响应转发给其它的目标受众Actor,后者也可以进行响应/转发/产生副作用。Router和Supervisor就是这种情况。(很快我们就会看到)
请求及响应
本文中我们只关注第一点——请求及响应周期。
这张图说明了我们这次要做的事情。为了简单点,图中我并没有画出ActorSystem, Dispatcher以及Mailbox。
1. DriverApp将一条InitSignal消息发送给StudentActor。
2. StudentActor响应InitSignal消息并将一条QuoteRequest消息发送到TeacherActor。
3. 正如前面所说的那样,TeacherActor会回复一个QuoteResponse。
4. StudentActor将日志打印到控制台或者logger里。
同样的,我们会写一个测试用例来验证下它。
现在我们来仔细地分析下这四个步骤:
1. DRIVERAPP将一条INITSIGNAL消息发送给STUDENTACTOR
现在你应该能猜到DriverApp到底是干什么的了。它只做了4件事情:
1. 初始化ActorSystem
//Initialize the ActorSystem
val system = ActorSystem("UniversityMessageSystem”)
2. 创建TeacherActor
//create the teacher actor
val teacherRef = system.actorOf(Props[TeacherActor], "teacherActor”)
3. 创建StudentActor
//create the Student Actor - pass the teacher actorref as a constructor parameter to StudentActor
val studentRef = system.actorOf(Props(new StudentActor(teacherRef)), "studentActor")
你会注意到我把TeacherActor的一个ActorRef的引用作为构造函数的参数传给了StudentActor,这样StudentActor才能够通过ActorRef来将消息发送给TeacherActor。当然还有别的方法(比如通过
Props来传递),不过这么做对后续即将讲到的Supervisor和Router来说会方便一点。很快我们会看到子Actor也能实现这个功能,不过那个方法用在这里并不适合——学生来生成老师,这看起来不太对劲吧?
最后,
4. DriverApp将InitSignal消息发送给了StudentActor,这样StudentActor会开始将QuoteRequest消息发送给TeacherActor。
//send a message to the Student Actor
studentRef ! InitSignal
DriverClass讲的已经够多了。后面的Thread.sleep和ActorSystem.shutdown就是等了几秒,以便消息发送完成,然后再最终将ActorSystem关掉。
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. STUDENTACTOR响应INITSIGNAL消息并将QUOTEREQUEST消息发送给TEACHERACTOR
以及
4. STUDENTACTOR接收到TEACHERACTOR回复的QuoteResponse然后将日志打印到控制台/logger上来
为什么我把第2和第4点放到一起来讲?因为它太简单了,如果分开讲的话我怕你嫌我啰嗦。
那么,第2步——StudentActor接收到DriverApp发过来的InitSingal消息并将QuoteRequest发送给TeacherActor。
def receive = {
case InitSignal=> {
teacherActorRef!QuoteRequest
}
...
...
搞定!
第4步——StudentActor将TeacherActor发过来的消息打印出来。
说到做到:
case QuoteResponse(quoteString) => {
log.info ("Received QuoteResponse from Teacher")
log.info(s"Printing from Student Actor $quoteString")
}
我猜你肯定觉得这很像是伪代码。
那么,完整的StudentActor应该是这样的:
STUDENTACTOR.SCALA
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. TeacherActor回复QuoteResponse
这和我们在前面的
fire-n-forget那篇)中看到的代码是类似的。
TeacherActor接收到QuoteRequest消息然后回复一个QuoteResponse。
TEACHERACTOR.SCALA
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应用。
原创文章转载请注明出处:
http://it.deepinmind.com
英文原文链接
分享到:
相关推荐
响应式架构 消息模式Actor实现与Scala.Akka应用集成 响应式架构 消息模式Actor实现与Scala.Akka应用集成
网络上各系统进行交互的困难之处,并介绍如何使用 Akka 提供的解决方案来解决这些 问题。 作者简介 Jason Goodwin 是一个基本上通过自学成才的开发者。他颇具企业家精神,在学校 学习商学。不过他从 15 岁起就开始...
响应式架构++消息模式Actor实现与Scala.Akka应用集成+,沃恩·弗农+
响应式架构 消息模式Actor实现与Scala.Akka应用集成 高清扫描版
其中包括:Actor模型和响应式软件的主要概念、Scala语言的基础知识、Akka框架与Akka集群功能、Actor模型中的通道机制和技术、降低消息源与消息目的地之间耦合性的方式、持久化Actor对象和幂等接收者。附录A中还介绍...
akka实例 java实现tcp远程调用,一个服务端,一个客户端
响应式架构 消息模式Actor实现与Scala.Akka应用集成 ,沃恩·弗农
Akka is a distributed computing toolkit that enables developers to build correct concurrent and distributed applications using Java and Scala with ease, applications that scale across servers and ...
网络上各系统进行交互的困难之处,并介绍如何使用 Akka 提供的解决方案来解决这些 问题。 作者简介 Jason Goodwin 是一个基本上通过自学成才的开发者。他颇具企业家精神,在学校 学习商学。不过他从 15 岁起就开始...
Akka笔记 Akka消息 文档 源代码 从 Akka记录 文档 源代码 从 Akka测试 文档 源代码 从 Akka消息传递请求和响应 文档 源代码 从arunma / AkkaMessagingRequestResponse分叉
Akka Essentials,学习akka很好的一本书
akka学习入门实践
Akka in Action shows you how to build message-oriented systems with Akka. This comprehensive, hands-on tutorial introduces each concept with a working example. You’ll start with the big picture of ...
Learning Akka Learning Akka Learning AkkaLearning Akka
akka 实战。akka in action。v13 2014新版。 互联网技术入门必备 清晰,非扫描。
akka-kryo-serialization, 基于Kryo的Akka序列化 akka-kryo-serialization-- Scala 和Akka基于kryo的序列化程序这个库为 Scala 和Akka提供定制的基于kryo的序列化程序。 它可以用于更高效的akka远程处理。它还可以...
Akka Concurrency