[翻译]AKKA笔记 - ACTOR MESSAGING - REQUEST AND RESPONSE -3
上次我们看Actor消息机制,我们看到开火-忘记型消息发出(意思是我们只要发个消息给Actor但是不期望有响应)。
技术上来讲, 我们发消息给Actors就是要它的副作用。 这就是这么设计的。除了不响应, 目标Actor当然也可以对消息做以下事情-
1.发送一个响应给发送者(在我们的case里,TeacherActor应该响应一首名言给StudentActor)
2.转发一个响应给其他的潜在的受众Actor,他们也可能响应/转发/产生副作用。Routers(路由)和Supervisors(监管)就是这个例子。(我们马上就能看到)
REQUEST & RESPONSE
这次,我们只关注第一点- 请求-响应的周期。

图片说明了我们这次在尝试归档做什么。为了简介,我没有在图中加入ActorSystem, Dispathcer或Mailboxes。
DriverApp发送一个InitSignal(初始化信号)消息给StudentActor.
StudentActor反馈给InitSignal消息并且发送一条QuoteRequest(格言请求)消息给TeacherActor。
TeacherActor,像我们在第一次看到的,响应一条QuoteResponse。
StudentActor只记录QuoteResponse(格言响应)到控制台/日志记录器。
我们可以写个testcase来验证。
让我们看下这4点的细节:
1. DRIVERAPP发送一个INITSIGNAL消息给STUDENTACTOR

至此,你可能已经猜出DriverApp会做什么。 就4件事:
1) 初始化ActorSystem
//Initialize the ActorSystem
  val system = ActorSystem("UniversityMessageSystem")
- 创建TeacherActor
 
//create the teacher actor
  val teacherRef = system.actorOf(Props[TeacherActor], "teacherActor")
- 创建StudentActor
 
//create the Student Actor - pass the teacher actorref as a constructor parameter to StudentActor
  val studentRef = system.actorOf(Props(new StudentActor(teacherRef)), "studentActor")
你可以看到我把ActorRef的实例TeacherActor给StudentActor的构造函数,这样StudentActor可以使用ActorRef发消息给TeacherActor。还有另外的方式达到这个目的(如传入Props),但是这个方法对我们后面看到的Supervisors和Routers会方便点。我们也会即将看到child actors但现在还不是一个好方式 - Student创建Teacher听起来怪怪的吧?
最后,
4) DriverApp会发一个InitSignal给StudentActor, z何阳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并且将日志记录到控制台/日志记录器###
为什么我把2和4条绑在一起?因为实在太简单了,要是拆开来你要恨死我。

所以,第二点 - StudentActor从DriverApp接到InitSignal消息并且发送QuoteRequest给TeacherActor。
def receive = {
    case InitSignal=> {
          teacherActorRef!QuoteRequest
    }
    ...
    ...
就这么多!
第四点 - 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
    }
  }
}
测试用例TESTCASES###
现在,我们的测试用例会模拟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的schedulers并且用Kamon监控你的Akka应用。
文章来自微信平台「麦芽面包」,微信号「darkjune_think」。转载请注明。
[翻译]AKKA笔记 - ACTOR MESSAGING - REQUEST AND RESPONSE -3的更多相关文章
- [翻译]AKKA笔记 -ACTOR SUPERVISION - 8
		
失败更像是分布式系统的一个特性.因此Akka用一个容忍失败的模型,在你的业务逻辑与失败处理逻辑(supervision逻辑)中间你能有一个清晰的边界.只需要一点点工作,这很赞.这就是我们要讨论的主题. ...
 - [翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5
		
原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/ (请注意这了讨论的生命周期并不包括 preRestart 或者pos ...
 - 翻译:AKKA笔记 - Actor消息 -1(一)
		
从第一篇Akka笔记的介绍中,我们是从很高的高度去观察Akka工具箱中的Actors.在这篇笔记的第二篇,我们会看一下Actors中的消息部分.而且延续上一次的例子,我们还会使用同样的学生与老师的例子 ...
 - 翻译:AKKA笔记 - Actor消息 -1(二)
		
消息 我们只是让QuoteRequest到ActorRef去但是我们根本没见过消息类! 它是这样的: (一个最佳实践是把你的消息类包装在一个完整的对象里以利于更好的组织) TeacherProtoco ...
 - [翻译]AKKA笔记 - DEATHWATCH -7
		
当我们说Actor生命周期的时候,我们能看到Actor能被很多种方式停掉(用ActorSystem.stop或ActorContext.stop或发送一个PoisonPill - 也有一个kill和g ...
 - [翻译] AKKA笔记- ACTORSYSTEM (配置CONFIGURATION 与调度SCHEDULING) - 4(一)
		
原文在http://rerun.me/2014/10/06/akka-notes-actorsystem-in-progress/ 像我们前面看到的,我们可以用ActorSystem的actorof方 ...
 - [翻译]AKKA笔记 - LOGGING与测试ACTORS -2 (一)
		
在前两章 ( 一 , 二 ) ,我们大致讲了Actor和message是怎么工作的,让我们看一下日志和测试我们的 TeacherActor . RECAP 这是上一节我们的Actor代码: class ...
 - [翻译]AKKA笔记 - 有限状态机 -1
		
原文地址:http://rerun.me/2016/05/21/akka-notes-finite-state-machines-1/ 我最近有个机会在工作上使用了Akka FSM,是个非常有趣的例子 ...
 - [翻译]AKKA笔记 - CHILD ACTORS与ACTORPATH -6
		
原文:http://rerun.me/2014/10/21/akka-notes-child-actors-and-path/ Actor是完全的继承结构.你创建的任何Actor肯定都是一个其他Act ...
 
随机推荐
- 硬浮点 VFP
			
http://blog.chinaunix.net/uid-27875-id-3449290.html 编译器对VFP的支持一个浮点数操作最后是翻译成VFP指令,还是翻译成fpa,或者是softf ...
 - Java正则表达式的解释说明
			
1.字符x 字符 x.例如a表示字符a\\ 反斜线字符.在书写时要写为\\\\.(注意:因为java在第一次解析时,把\\\\解析成正则表达式\\,在第二次解析时再解析为\,所以凡是不是1 ...
 - 【转】webGL与OpenGL的不同
			
原链接 http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences WebGL and OpenGL Differences ...
 - sql连着function使用
			
create function fun002(@thename varchar()) returns int as begin declare @count int select @count=cou ...
 - Dojo框架学习笔记<二>
			
一.dojo/dom 该模块定义了Dojo Dom API,主要有以下几种用法: 1.dom.byId();(相当于document.getElementById()) ①最直接的用 ...
 - 【CronExpression表达式详解和案例】
			
1. cron表达式格式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)} 2. cron表达式各占位符解释: {秒数} ==> 允许值范围: 0~59 ,不允许 ...
 - angular js 的 ng-keyup 监听 keydown keyup事件获取 keyCode
			
参考这个页面.http://www.angularjshub.com/examples/eventhandlers/keyboardevents/ Html页面代码: <input ng-mod ...
 - JavaScript-永远点不到的小窗口
			
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...
 - shell选择语句
			
if语句 1) if ... else 语句 if ... else 语句的语法: if [ expression ] then Statement(s) to be executed if expr ...
 - git svn clone时间估算
			
处理器: Intel(R) Xeon(R) CPU E5-2620 @2.00GHz 2.00Ghz 内存:32.0 GB 操作系统: Windows Server 2008 R2 Enterpris ...