设为首页 加入收藏

TOP

使用Akka Actor和Java 8构建反应式应用(二)
2017-12-29 06:07:18 】 浏览:444
Tags:使用 Akka Actor Java 构建 反应 应用
理的消息,另外还包含消息如何进行处理的实现。


如果这个签名看上去令人望而生畏的话,那么我们的代码可以通过前面所使用的ReceiveBuilder将细节隐藏起来。


需要注意最后对receive的调用,将默认行为设置为“disabled”。这三个行为是使用已有的三个方法(onActivity、onDisable、onEnable)来实现的。这些方法中最简单的是onActivity。如果接收到activity的话,报警会在控制台记录一条日志。在这里需要注意activity没有消息负载,所以我们将其命名为ignored。 


如果Actor接收到一条enable消息的话,新的状态将会记录下来并且状态将会变更为enabled。如果密码不匹配的话,会记录一条简短的警告日志。消息负载现在包含了密码,所以我们可以通过访问它来校验密码。


当收到一条disable消息时,Actor需要检查密码,记录一条关于状态变化的简短消息然后将状态修改为disabled或者在密码不匹配的情况下记录一条警告信息。


这样就完成了Actor的逻辑,我们接下来可以启动Actor系统并向其发送一些消息。注意,我们的正确密码“cats”是作为一个属性传递给Actor系统的。


消息:


产生的输出如下所示:


你可以在GitHub上找到完整的可运行样例。到目前为止,我们只使用了一个Actor来处理消息。不过就像在业务组织中一样,Actor也能形成自然的层级结构。


Actor可能会创建其他的Actor。当一个Actor创建另外一个Actor时,创建者也被称为监管者(supervisor),而被创建的Actor也被称为工作者(worker)。我们可能基于很多原因需要创建工作者Actor,最常见的原因是工作的委托。监管者创建一个或多个工作者Actor,然后将工作委托给它们。


监管者同时会成为工作者的看守人。就像父母会时刻关注孩子的行为那样,监管者也会照顾它的工作者Actor。如果Actor遇到问题的话,它会将自己挂起(也就是说在恢复之前,它不会处理正常的消息),并且会通知其监管者自己发生了故障。


到目前为止,我们创建了多个Actor并为其分配了名字。Actor的名字用来在层级结构中识别Actor。与Actor交互的一般都是用户所创建Actor的父Actor,也就是带有"/user"路径的guardian。使用原始system.actorOf()创建的Actor是该guardian的直接子Actor,如果它终止的话,系统中所有正常的Actor也都会关闭。在上面的alarm样例中,我们创建的是/user/alarm路径的用户Actor。因为Actor是按照严格的层级方式来创建的,所以Actor会存在一个由Actor名称组成的唯一序列,这个序列会从Actor系统的根逐级往下,按照父子关系形成。这个序列类似于文件系统中的封闭文件夹,因此采用了“路径(path)”这个名称来代指它,当然Actor层级结构与文件系统的层级结构还有一些基础的差异。


在Actor内部,我们可以调用getContext().actorOf(props, “alarm-child”)创建名为“alarm-child”的新Actor,它会作为alarm Actor的子Actor。子Actor的生命周期是绑定在父Actor之上的,这意味着如果我们停止“alarm” Actor的话,也会停掉其子Actor:


使用Akka Actor和Java 8构建反应式应用


这种层级结构对于基于Actor系统的故障处理也有着直接影响。Actor系统的典型特点就是将任务进行分解和委托,直到它被拆分得足够小,能够从一个地方进行处理。通过这种方式,不仅任务本身能够非常清晰地进行结构化,所形成的Actor也能在如下方面变得非常明确:


如果某个Actor无法处理特定情景的话,它会发送对应的故障消息给它的监管者,请求帮助。面对故障,监管者有四种不同的可选方案:


接下来,我们将上面学到的所有内容通过一个样例来具体讲解一下:NonTrustWorthyChild接收Command消息,每当收到该消息时,会增加一个内部的计数器。如果消息数能够被4整除的话,会抛出一个RuntimeException,这个异常会向上传递给Supervisor。这里并没有什么新东西,Command消息本身并没有负载。


Supervisor 在它的构造器中启动NonTrustWorthyChild,并将它所接收到的command消息直接转发给子Actor。


Supervisor实际启动之后,所形成的层级结构将会是“/user/supervisor/child”。在我们完成该任务之前,需要预先定义所谓的监管策略(supervision strategy)。Akka提供了两种类型的监管策略:OneForOneStrategyAllForOneStrategy。它们之间的差异在于前者会将指令应用于发生故障的子Actor,而后者则会将指令同时应用于子Actor的兄弟节点。正常情况下,我们应该使用OneForOneStrategy,如果没有明确声明的话,它也是默认方案。监管策略需要通过覆盖SupervisorStrategy方法来定义。


第一个参数定义了maxNrOfRetries,它指定了子Actor在停止之前允许尝试重启的次数。(如果设置为负数值,则代表没有限制)。withinTimeRange参数定义了maxNrOfRetries的持续时间窗口。按照上面的定义,该策略会在10秒钟之内尝试10次。DeciderBuilder的工作方式与ReceiveBuilder完全类似,它定义了要匹配的异常以及如何应对。在本例中,如果在10秒钟内尝试了10次的话,Supervisor会停止掉NonTrustWorthyChild,所有剩余的消息将会发送至dead letter box。


Actor系统是通过Supervisor Actor来启动的。


当系统启动之后,我们发送10条command信息到Supervisor。需要注意,“Command”消息是定义在NonTrustWorthyChild中的。


输出的内容显示,在四条消息之后,异常传递到了Supervisor中,剩下的消息发送到了deadLetters收件箱中。如果SupervisorStrategy被定义为restart()而不是stop()的话,那么将会启动一个新的NonTrustWorthyChild Actor实例。


这个日志可以关闭或者进行调整,这需要修改 “akka.log-dead-letters”“akka.log-dead-letters-during-shutdown”的配置。


读者可以在线查看完整的样例,并尝试调整SupervisorStrategy


借助Akka和Java 8,我们能够创建分布式和基于微服务的系统,这在几年前还是一种梦想。现在,所有行业的企业都迫切希望系统的演化速度能够跟上业务的速度和用户的需求。如今,我们能够弹性的扩展系统,使其支持大量的用户和庞大的数据。我们创建的系统有望具备一定级别的弹性,使停机时间不再是按照小时来计算,而是按照秒来计算。基于Actor的系统能够让我们创建快速演进的微服务架构,它可以进行扩展并且能够不停机运行。


Actor模型提供

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Nodejs 做后台完整业务案例 下一篇Shell按行读取文件

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目