`
deepinmind
  • 浏览: 453377 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
1dc14e59-7bdf-33ab-841a-02d087aed982
Java函数式编程
浏览量:41781
社区版块
存档分类
最新评论

Akka笔记之请求与响应

阅读更多
前面我们讲到了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

英文原文链接


1
0
分享到:
评论

相关推荐

    响应式架构 消息模式Actor实现与Scala.Akka应用集成

    响应式架构是一种设计模式,...而提供的"响应式架构 消息模式Actor实现与Scala.Akka应用集成"文档,很可能是对这些概念的详细讲解,包括沃恩·弗农的观点和实践经验,对于深入理解Akka和响应式架构有着重要的参考价值。

    响应式架构++消息模式Actor实现与Scala.Akka应用集成+,沃恩·弗农+

    在《响应式架构++消息模式Actor实现与Scala.Akka应用集成+》中,作者沃恩·弗农深入探讨了如何利用Akka和Scala来构建响应式的应用程序。他可能详细讲解了以下知识点: 1. **Actor系统**:介绍Akka中的Actor系统是...

    响应式架构 消息模式Actor实现与Scala.Akka应用集成 ,沃恩·弗农

    响应式架构是一种设计思想,它强调系统在面对不断变化的工作负载和网络延迟时,能够保持弹性、反应迅速...阅读"响应式架构 消息模式Actor实现与Scala.Akka应用集成"这本书,将有助于你掌握这些概念并应用于实际项目中。

    Akka入门与实践

    网络上各系统进行交互的困难之处,并介绍如何使用 Akka 提供的解决方案来解决这些 问题。 作者简介 Jason Goodwin 是一个基本上通过自学成才的开发者。他颇具企业家精神,在学校 学习商学。不过他从 15 岁起就开始...

    akka java实现tcp远程调用

    下面我们将深入探讨如何使用Akka与Java来实现TCP远程调用,以及其中涉及的关键知识点。 首先,我们需要理解Akka的Actor系统。Actor是Akka的核心概念,每个Actor都是一个独立的执行单元,拥有自己的状态和邮箱,用于...

    Akka 实战 akka in action v13 2014版本

    Akka可以与现有的技术栈和消息系统集成,这让开发者能够更容易地在现有架构中引入Akka。 集群功能是Akka的另一亮点,它使得开发者能够将多个Akka节点组成一个集群,从而实现更高的性能和更好的容错性。集群中的节点...

    akka学习入门实践

    - **Akka 中的应用**:Akka 支持通过 Future 和 Promise API 实现异步操作,这有助于构建响应式的系统。 - **优势**:提高了系统的并发能力和用户体验,减少了等待时间。 #### 四、Akka 消息传递模式 - **核心机制*...

    响应式架构 消息模式Actor实现与Scala.Akka应用集成 高清扫描版

    响应式架构 消息模式Actor实现与Scala.Akka应用集成 高清扫描版

    响应式架构 消息模式Actor实现与Scala.Akka应用集成.rar

    其中包括:Actor模型和响应式软件的主要概念、Scala语言的基础知识、Akka框架与Akka集群功能、Actor模型中的通道机制和技术、降低消息源与消息目的地之间耦合性的方式、持久化Actor对象和幂等接收者。附录A中还介绍...

    c#分布式框架akka范例

    使用`Tell`方法非阻塞地发送消息,而`Ask`方法则允许异步请求-响应模式。 3. **远程通信**:Akka.NET的Remote功能使得Actor可以在不同的网络节点上运行。这使得构建分布式系统成为可能,Actor可以通过网络透明地...

    akka-http-1.0-RC2.jar.zip

    1. **响应式设计**:Akka HTTP遵循响应式宣言,确保了系统对请求的快速响应,同时保持资源的高效利用和良好的弹性。 2. **流式处理**:支持HTTP/2协议,可以处理数据流,允许数据在请求和响应之间无缝传输,减少了...

    Learning Akka

    10. **集成和测试**:了解如何将Akka与其他技术(如 Spray for RESTful服务、Cassandra for分布式数据存储)集成,以及如何编写有效的Akka测试,都是学习过程中的重要部分。 通过阅读《Learning Akka》,开发者不仅...

    akka实例参考

    10. **事件驱动和响应式编程**:Akka遵循响应式宣言,强调非阻塞I/O、背压和弹性,使其非常适合构建高性能、低延迟的应用。 11. **Future和Promise**:Akka中的Future代表一个异步计算的结果,Promise则是用来设置...

    Learning Akka(PACKT,2015)

    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 ...

    java解决AKKA的疑点难点.docx

    7. **将HTTP请求异步接管到Akka集群**:AKKA-HTTP与Akka Actor系统紧密集成,可以将HTTP请求转换为消息并异步处理。如`websocketFlow`中的`actor.tell`方法,将接收到的消息发送到actor系统,实现非阻塞处理。 在...

    Akka.net分布式数据传输

    在分布式系统中,数据传输是核心功能之一,Akka.NET 提供了高效且可靠的手段来实现在网络中的节点间通信。本文将深入探讨 Akka.NET 的分布式数据传输机制及其应用。 ### 1. Akka.NET 概述 Akka.NET 是基于 Actor ...

Global site tag (gtag.js) - Google Analytics