当我们说Actor生命周期的时候,我们能看到Actor能被很多种方式停掉(用ActorSystem.stop或ActorContext.stop或发送一个PoisonPill - 也有一个killgracefulstop)。

无论Actor是怎么死的,有些情况一些系统中的其他actor想要知道。让我们举一个Actor与数据库交互的例子 - 我们叫它RepositoryActor。很明显,会有一些其他actor会向这个RepositoryActor发送消息。这些有“兴趣”的Actor很愿意留个eye或者看(watch)这个actor关闭时的消息。这个在Actor里面叫DeathWatch。这个用来watchunwatch的方法就是ActorContext.watchActorContext.unwatch。如果已经监视了,这些watcher会在Actor关闭时收到一个Terminated消息,并可以很舒服的加到他们的receive功能中。

不像Supervision有一个严格的父子继承关系,任何Actor都可以watch任何ActorSystem中的Actor。

让我们看下。

代码

QUOTEREPOSITORYACTOR

1.我们的QueryRepositoryActor格言查询Actor保存了一个quote的列表并且在收到一个QuoteRepositoryRequest时随机返回一条。

  1. 他记录了收到消息的个数,如果收到超过3个消息,他用PoisonPill把自己杀掉

这没啥神奇的。

  1. package me.rerun.akkanotes.deathwatch
  2. import akka.actor.{PoisonPill, Actor, ActorLogging, actorRef2Scala}
  3. import me.rerun.akkanotes.protocols.QuoteRepositoryProtocol._
  4. import scala.util.Random
  5. class QuoteRepositoryActor() extends Actor with ActorLogging {
  6. val quotes = List(
  7. "Moderation is for cowards",
  8. "Anything worth doing is worth overdoing",
  9. "The trouble is you think you have time",
  10. "You never gonna know if you never even try")
  11. var repoRequestCount:Int=1
  12. def receive = {
  13. case QuoteRepositoryRequest => {
  14. if (repoRequestCount>3){
  15. self!PoisonPill
  16. }
  17. else {
  18. //Get a random Quote from the list and construct a response
  19. val quoteResponse = QuoteRepositoryResponse(quotes(Random.nextInt(quotes.size)))
  20. log.info(s"QuoteRequest received in QuoteRepositoryActor. Sending response to Teacher Actor $quoteResponse")
  21. repoRequestCount=repoRequestCount+1
  22. sender ! quoteResponse
  23. }
  24. }
  25. }
  26. }

TEACHERACTORWATCHER

一样的,TeacherActorWatcher也没啥神奇的,除了他创建了一个QuoteRepositoryActor并且用context.watch观察。

  1. package me.rerun.akkanotes.deathwatch
  2. import akka.actor.{Terminated, Props, Actor, ActorLogging}
  3. import me.rerun.akkanotes.protocols.TeacherProtocol.QuoteRequest
  4. import me.rerun.akkanotes.protocols.QuoteRepositoryProtocol.QuoteRepositoryRequest
  5. class TeacherActorWatcher extends Actor with ActorLogging {
  6. val quoteRepositoryActor=context.actorOf(Props[QuoteRepositoryActor], "quoteRepositoryActor")
  7. context.watch(quoteRepositoryActor)
  8. def receive = {
  9. case QuoteRequest => {
  10. quoteRepositoryActor ! QuoteRepositoryRequest
  11. }
  12. case Terminated(terminatedActorRef)=>{
  13. log.error(s"Child Actor {$terminatedActorRef} Terminated")
  14. }
  15. }
  16. }

测试CASE

这里会有点意思。我从来没想过这个可以被测试。akka-testkit。我们会分析下这三个测试CASE:

1. 断言如果观察到已经收到Terminated消息

QuoteRepositoryActor应该在收到第四条消息时给测试case发送一条Terminated消息。前三条应该是可以的。

  1. "A QuoteRepositoryActor" must {
  2. ...
  3. ...
  4. ...
  5. "send back a termination message to the watcher on 4th message" in {
  6. val quoteRepository=TestActorRef[QuoteRepositoryActor]
  7. val testProbe=TestProbe()
  8. testProbe.watch(quoteRepository) //Let's watch the Actor
  9. within (1000 millis) {
  10. var receivedQuotes = List[String]()
  11. (1 to 3).foreach(_ => quoteRepository ! QuoteRepositoryRequest)
  12. receiveWhile() {
  13. case QuoteRepositoryResponse(quoteString) => {
  14. receivedQuotes = receivedQuotes :+ quoteString
  15. }
  16. }
  17. receivedQuotes.size must be (3)
  18. println(s"receiveCount ${receivedQuotes.size}")
  19. //4th message
  20. quoteRepository!QuoteRepositoryRequest
  21. testProbe.expectTerminated(quoteRepository) //Expect a Terminated Message
  22. }
  23. }

2.如果没有观察(watched/unwatched)到则断言没收到Terminated消息

事实上,我们做这个只是演示下context.unwatch。如果我们移掉testProbe.watch和testProbe.unwatch这行,则测试case会运行的很正常。

  1. "not send back a termination message on 4th message if not watched" in {
  2. val quoteRepository=TestActorRef[QuoteRepositoryActor]
  3. val testProbe=TestProbe()
  4. testProbe.watch(quoteRepository) //watching
  5. within (1000 millis) {
  6. var receivedQuotes = List[String]()
  7. (1 to 3).foreach(_ => quoteRepository ! QuoteRepositoryRequest)
  8. receiveWhile() {
  9. case QuoteRepositoryResponse(quoteString) => {
  10. receivedQuotes = receivedQuotes :+ quoteString
  11. }
  12. }
  13. testProbe.unwatch(quoteRepository) //not watching anymore
  14. receivedQuotes.size must be (3)
  15. println(s"receiveCount ${receivedQuotes.size}")
  16. //4th message
  17. quoteRepository!QuoteRepositoryRequest
  18. testProbe.expectNoMsg() //Not Watching. No Terminated Message
  19. }
  20. }

3. 在TeacherActorWatcher中断言收到了Terminated消息

我们订阅了EventStream并通过检查一个特殊的日志消息来断言termination。

  1. "end back a termination message to the watcher on 4th message to the TeacherActor" in {
  2. //This just subscribes to the EventFilter for messages. We have asserted all that we need against the QuoteRepositoryActor in the previous testcase
  3. val teacherActor=TestActorRef[TeacherActorWatcher]
  4. within (1000 millis) {
  5. (1 to 3).foreach (_=>teacherActor!QuoteRequest) //this sends a message to the QuoteRepositoryActor
  6. EventFilter.error (pattern="""Child Actor .* Terminated""", occurrences = 1).intercept{
  7. teacherActor!QuoteRequest //Send the dangerous 4th message
  8. }
  9. }
  10. }

EventFilter中的pattern属性,没啥奇怪的,需要一个正则表达式。正则pattern="""Child Actor .* Terminated"""用来匹配一条格式是Child Actor {Actor[akka://TestUniversityMessageSystem/user/$$d/quoteRepositoryActor#-1905987636]} Terminated日志信息。

Github###

与往常一样,代码在github。看下deathwatch的包。


文章来自微信平台「麦芽面包」(微信扫描二维码关注)。未经允许,禁止转载。

[翻译]AKKA笔记 - DEATHWATCH -7的更多相关文章

  1. [翻译]AKKA笔记 -ACTOR SUPERVISION - 8

    失败更像是分布式系统的一个特性.因此Akka用一个容忍失败的模型,在你的业务逻辑与失败处理逻辑(supervision逻辑)中间你能有一个清晰的边界.只需要一点点工作,这很赞.这就是我们要讨论的主题. ...

  2. [翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5

    原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/ (请注意这了讨论的生命周期并不包括 preRestart 或者pos ...

  3. [翻译] AKKA笔记- ACTORSYSTEM (配置CONFIGURATION 与调度SCHEDULING) - 4(一)

    原文在http://rerun.me/2014/10/06/akka-notes-actorsystem-in-progress/ 像我们前面看到的,我们可以用ActorSystem的actorof方 ...

  4. [翻译]AKKA笔记 - 有限状态机 -1

    原文地址:http://rerun.me/2016/05/21/akka-notes-finite-state-machines-1/ 我最近有个机会在工作上使用了Akka FSM,是个非常有趣的例子 ...

  5. [翻译]AKKA笔记 - CHILD ACTORS与ACTORPATH -6

    原文:http://rerun.me/2014/10/21/akka-notes-child-actors-and-path/ Actor是完全的继承结构.你创建的任何Actor肯定都是一个其他Act ...

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

    上次我们看Actor消息机制,我们看到开火-忘记型消息发出(意思是我们只要发个消息给Actor但是不期望有响应). 技术上来讲, 我们发消息给Actors就是要它的副作用. 这就是这么设计的.除了不响 ...

  7. [翻译]AKKA笔记 - LOGGING与测试ACTORS -2 (二)

    3.THROW IN A LOGBACK.XML 现在我们把SLF4J日志配置在logback. <?xml version="1.0" encoding="UTF ...

  8. [翻译]AKKA笔记 - LOGGING与测试ACTORS -2 (一)

    在前两章 ( 一 , 二 ) ,我们大致讲了Actor和message是怎么工作的,让我们看一下日志和测试我们的 TeacherActor . RECAP 这是上一节我们的Actor代码: class ...

  9. 翻译:AKKA笔记 - Actor消息 -1(一)

    从第一篇Akka笔记的介绍中,我们是从很高的高度去观察Akka工具箱中的Actors.在这篇笔记的第二篇,我们会看一下Actors中的消息部分.而且延续上一次的例子,我们还会使用同样的学生与老师的例子 ...

随机推荐

  1. 逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])

    常用技能:http://www.cnblogs.com/dunitian/p/4822808.html#skill 逆天博客:http://dnt.dkil.net 逆天通用水印扩展篇~新增剪贴板系列 ...

  2. javascript中的继承与深度拷贝

    前言 本篇适合前端新人,下面开始...... 对于前端新手来说(比如博主),每当对js的对象做操作时,都是一种痛苦,原因就是在于对象的赋值是引用的传递,并非值的传递,虽然看上去后者赋值给了前者,他们就 ...

  3. 如何利用pt-online-schema-change进行MySQL表的主键变更

    业务运行一段时间,发现原来的主键设置并不合理,这个时候,想变更主键.这种需求在实际生产中还是蛮多的. 下面,看看pt-online-schema-change解决这类问题的处理方式. 首先,创建一张测 ...

  4. vue.js学习笔记

    有了孩子之后,元旦就哪也去不了了(孩子太小),刚好利用一些时间,来公司充充电补补课,学习学习新技术,在这里做一个整理和总结.(选择的东西,既然热爱就把他做好吧!). 下来进入咱们的学习环节: 一.从H ...

  5. JQuery的基础和应用

    <参考文档>   1.什么是?    DOM的作用:提供了一种动态的操作HTML元素的方法.    jQuery是一个优秀的js库.用来操作HTML元素的工具.    jQuery和DOM ...

  6. Linux系统中的Device Mapper学习

    在linux系统中你使用一些命令时(例如nmon.iostat 如下截图所示),有可能会看到一些名字为dm-xx的设备,那么这些设备到底是什么设备呢,跟磁盘有什么关系呢?以前不了解的时候,我也很纳闷. ...

  7. 通过Mono 在 Heroku 上运行 .NET 应用

    英文原文:Running .NET on Heroku 中文原文:在 Heroku 上运行 .NET 应用 自从加入了Heroku之后,我就想在这个平台上运行.NET程序.现在我很高兴向大家宣布,我们 ...

  8. 谁偷了我的热更新?Mono,JIT,iOS

    前言 由于匹夫本人是做游戏开发工作的,所以平时也会加一些玩家的群.而一些困扰玩家的问题,同样也困扰着我们这些手机游戏开发者.这不最近匹夫看自己加的一些群,常常会有人问为啥这个游戏一更新就要重新下载,而 ...

  9. C#与yaml解析

    YAML 官方网站称 YAML 是"一种所有编程语言可用的友好的数据序列化标准".YAML Ain't Markup Language,和GNU一样,YAML是一个递归着说&quo ...

  10. 【腾讯Bugly干货分享】React Native项目实战总结

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...