[翻译]AKKA笔记 - ACTOR MESSAGING - REQUEST AND RESPONSE -3

news/2024/7/1 20:45:11

上次我们看Actor消息机制,我们看到开火-忘记型消息发出(意思是我们只要发个消息给Actor但是不期望有响应)。

技术上来讲, 我们发消息给Actors就是要它的副作用。 这就是这么设计的。除了不响应, 目标Actor当然也可以对消息做以下事情-

1.发送一个响应给发送者(在我们的case里,TeacherActor应该响应一首名言给StudentActor

2.转发一个响应给其他的潜在的受众Actor,他们也可能响应/转发/产生副作用。Routers(路由)和Supervisors(监管)就是这个例子。(我们马上就能看到)


REQUEST & RESPONSE
这次,我们只关注第一点- 请求-响应的周期。
图片描述

图片说明了我们这次在尝试归档做什么。为了简介,我没有在图中加入ActorSystem, Dispathcer或Mailboxes。

  1. DriverApp发送一个InitSignal(初始化信号)消息给StudentActor.

  2. StudentActor反馈给InitSignal消息并且发送一条QuoteRequest(格言请求)消息给TeacherActor

  3. TeacherActor,像我们在第一次看到的,响应一条QuoteResponse

  4. StudentActor只记录QuoteResponse(格言响应)到控制台/日志记录器。

我们可以写个testcase来验证。

让我们看下这4点的细节:

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")

你可以看到我把ActorRef的实例TeacherActorStudentActor的构造函数,这样StudentActor可以使用ActorRef发消息给TeacherActor。还有另外的方式达到这个目的(如传入Props),但是这个方法对我们后面看到的Supervisors和Routers会方便点。我们也会即将看到child actors但现在还不是一个好方式 - Student创建Teacher听起来怪怪的吧?

最后,

4) DriverApp会发一个InitSignalStudentActor, z何阳StudentActor就能开始发送QuoteRequest(格言请求)给TeacherActor。

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

这个DriverClass讲差不多了。 Thread.sleepActorSystem.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. STUDENTACTORTEACHERACTOR接收到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」。转载请注明。


http://www.niftyadmin.cn/n/4429300.html

相关文章

robot pose ekf

参考链接 github源码 https://github.com/ros-planning/navigation/tree/kinetic-devel/robot_pose_ekf创客智造教程 https://www.ncnynl.com/archives/201708/1909.htmlcsdn修改参考https://blog.csdn.net/shenghuaijing3314/article/details/78220151 …

Windows Service 开发,安装与调试

Visual Studio.net 2010 Windows Service 开发,安装与调试 本示例完成一个每隔一分钟向C:\log.txt文件写入一条记录为例,讲述一个Windows Service 程序的开发,安装与调试 原程序,加文档示例下载 /Files/zycblog/SourceCode.rar 目录索引 1 开发工具…

ros cartographer安装,使用和修改

安装3个软件包,ceres solver cartographer cartographer_ros 有梯子的同学建议走官方版 https://google-cartographer-ros.readthedocs.io/en/latest/ 国内建议使用 https://www.cnblogs.com/hitcm/p/5939507.html https://www.cnblogs.com/BlueMountain-Hagg…

IOS之UIImageView--小实例项目--带音效的拳皇动画

内容大纲: 1、初步工作 2、开始敲代码 3、注意 4、可能遇到的错误 5、设置音频速率在代码顺序上的注意点 带音效的拳皇动画实例项目 初步工作 1、新建一Objective-C工程之后,将需要的拳皇动画实例的图片以及音效资源都拷贝进工程。 2、勾选,只…

php-fpm自启脚本

觉得手动操作php-fpm挺麻烦的,自己试着写一个脚本实现开机自启,实现了自己想要的效果。1、脚本#!/bin/bash #chkconfig: 2345 80 80 #description: auto start php-fpm daemon/usr/local/php/sbin/php-fpmcase $1 instart)proc_idecho $(netstat -lnutp | grep php…

git命令需要使用命令行开发者工具_java-性能调优命令行工具使用(jps....)

这篇仅仅记录参数使用,大多数还是需要自己琢磨同时还需要坚持:)jpsC:Users98du>jps -help usage: jps [-help]jps [-q] [-mlvV] [<hostid>]Definitions:<hostid>: <hostname>[:<port>]C:Users98du>参数说明-q : 进程id-m : 启动该…

Mac环境下Cocos2d-x开发环境完全指南

2019独角兽企业重金招聘Python工程师标准>>> 本教程主要指导新手在Mac环境下Cocos2d-x开发环境搭建。 1.Cocos2d-x下载 下载网站&#xff1a;http://cn.cocos2d-x.org/download/ 下载3.x版本后&#xff0c;解压即可 2.必备软件安装及环境配置 进行Cocos2d-x开发&…

1个系统节拍 c语言_疫情在家,开发了个低代码平台酒窝系统,演示 1 小时落地注册页面...

疫情在家&#xff0c;除了带娃也没有其他事情干&#xff0c;正好自己也一直想做一款业务中台系统&#xff0c;于是趁着这个时间&#xff0c;独自开发了低代码平台&#xff0c;耗时大概一个月&#xff0c;我叫她为 "酒窝"。19 年年中、末的时候&#xff0c;经常看见朋…