akka和rabbitmq_Akka Notes –演员记录和测试

akka和rabbitmq

在前两部分( 一 , 二 )中,我们简要讨论了Actor以及消息传递的工作方式。 在这一部分中,让我们看一下如何修复并记录我们的TeacherActor

回顾

这就是我们上一部分中的Actor的样子:

class TeacherActor extends Actor {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 responseval quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))println (quoteResponse)}}
}

使用SLF4J记录Akka

您会注意到,在代码中,我们正在将quoteResponse打印到标准输出,您显然同意这是一个坏主意。 让我们通过SLF4J Facade启用日志记录来解决此问题。

1.修复类以使用日志记录

Akka提供了一个很好的小特征ActorLogging来实现它。 让我们混合:

class TeacherLogActor 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 element (for now)val quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))log.info(quoteResponse.toString())}}//We'll cover the purpose of this method in the Testing sectiondef quoteList=quotes}

绕道而行:

在内部,当我们记录一条消息时,ActorLogging中的记录方法(最终)将日志消息发布到EventStream 。 是的,我确实说过publish 。 那么,EventStream实际上是什么?

EventStream和记录

EventStream行为就像可以向其发布和接收消息的消息代理一样。 与常规MOM的一个细微区别是EventStream的订阅者只能是Actor。

在记录消息的情况下,所有日志消息都将发布到EventStream。 默认情况下,订阅这些消息的Actor是DefaultLogger ,它仅将消息打印到标准输出中。

class DefaultLogger extends Actor with StdOutLogger {  override def receive: Receive = {...case event: LogEvent ⇒ print(event)}
}

因此,这就是我们尝试启动StudentSimulatorApp的原因,我们看到写入控制台的日志消息。

也就是说,Eve​​ntStream不仅适合于记录。 它是VM内ActorWorld内部可用的通用发布-订阅机制(稍后会详细介绍)。

返回SLF4J设置:

2.将Akka配置为使用SLF4J

akka{  loggers = ["akka.event.slf4j.Slf4jLogger"]loglevel = "DEBUG"logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
}

我们将此信息存储在名为application.conf的文件中,该文件应位于您的类路径中。 在我们的sbt文件夹结构中,我们将其放在您的main/resources目录中。

从配置中,我们可以得出:

  1. loggers属性指示要订阅日志事件的Actor。 Slf4jLogger所做的只是简单地使用日志消息并将其委托给SLF4J Logger外观。
  2. loglevel属性仅指示记录日志时应考虑的最低级别。
  3. logging-filter比较当前配置的日志loglevel和传入的日志消息级别,并在发布到EventStream之前剔除配置的日志级别以下的任何日志消息。

但是,为什么前面的示例没有提供application.conf?

仅仅是因为Akka提供了一些合理的默认值,所以我们在开始使用它之前不需要构建配置文件。 为了自定义各种内容,我们将在此频繁地重新访问此文件。 您可以在application.conf内部使用一堆很棒的参数来单独记录日志。 它们在这里详细解释。

3.放入logback.xml

现在,我们将配置一个由logback支持的SLF4J记录器。

<?xml version="1.0" encoding="UTF-8"?>  
<configuration>  <appender name="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>logs\akka.%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>50MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy></appender><root level="DEBUG"><appender-ref ref="FILE" /></root>
</configuration>

我也将它与application.conf一起放入了main/resources文件夹中。 请确保main/resources现在位于eclipse或其他IDE的类路径中。 还应将logback和slf4j-api包含到build.sbt中 。

而当我们揭开序幕我们StudentSimulatorApp和发送邮件到我们的新TeacherLogActor ,该akkaxxxxx.log文件,我们配置看起来像这样。

SLF4J记录

测试Akka

请注意,这绝不是Test Akka的详尽介绍。 我们将在以下各部分中相应标题下的“测试”的更多功能上构建测试。 这些测试用例旨在覆盖我们之前编写的Actor。

StudentSimulatorApp我们的需求时,您将同意应将其从测试用例中删除。

为了减轻测试的痛苦,Akka提出了一个了不起的测试工具包,使用它我们可以做一些神奇的事情,例如直接探查Actor实现的内部。

聊够了,让我们看看测试用例。

首先让我们尝试将StudentSimulatorApp映射到测试用例。

映射001

现在让我们单独看一下声明。

class TeacherPreTest extends TestKit(ActorSystem("UniversityMessageSystem"))  with WordSpecLikewith MustMatcherswith BeforeAndAfterAll {

因此,从TestCase类的定义中,我们看到:

  1. TestKit特性接受一个ActorSystem ,我们将通过该ActorSystem创建Actor。 在内部,TestKit装饰ActorSystem并替换默认的调度程序。
  2. 我们使用WordSpec ,这是使用ScalaTest编写测试用例的众多有趣方式之一。
  3. MustMatchers提供方便的方法来使测试用例看起来像自然语言
  4. 在测试用例完成之后,我们混合使用BeforeAndAfterAll来关闭ActorSystem。 特质提供的afterAll方法更像我们在JUnit中的tearDown

1、2 –向演员发送消息

  1. 第一个测试用例只是向PrintActor发送一条消息。 它没有断言!
  2. 第二种情况将消息发送到Log actor,后者使用ActorLogging的log字段将消息发布到EventStream。 这也没有断言!
//1. Sends message to the Print Actor. Not even a testcase actually"A teacher" must {"print a quote when a QuoteRequest message is sent" in {val teacherRef = TestActorRef[TeacherActor]teacherRef ! QuoteRequest}}//2. Sends message to the Log Actor. Again, not a testcase per se"A teacher with ActorLogging" must {"log a quote when a QuoteRequest message is sent" in {val teacherRef = TestActorRef[TeacherLogActor]teacherRef ! QuoteRequest}

3 –维护参与者的内部状态

第三种情况使用TestActorRefunderlyingActor quoteList方法,并调用TeacherActorquoteList方法。 quoteList方法返回引号列表。 我们使用此列表来声明其大小。

如果对quoteList引用使您退缩,请参考上面列出的TeacherLogActor代码,并查找:

//From TeacherLogActor
//We'll cover the purpose of this method in the Testing sectiondef quoteList=quotes
//3. Asserts the internal State of the Log Actor. "have a quote list of size 4" in {val teacherRef = TestActorRef[TeacherLogActor]teacherRef.underlyingActor.quoteList must have size (4)teacherRef.underlyingActor.quoteList must have size (4)}

4 –声明日志消息

正如我们前面在EventStream和Logging部分(上文)中讨论的那样,所有日志消息都进入EventStream ,并且SLF4JLogger订阅并使用其附加程序将其写入日志文件/控制台等。直接在我们的测试用例中使用EventStream并断言日志消息本身的存在? 看起来我们也可以做到。

这涉及两个步骤:

  1. 您需要像这样向您的TestKit添加额外的配置:
    class TeacherTest extends TestKit(ActorSystem("UniversityMessageSystem", ConfigFactory.parseString("""akka.loggers = ["akka.testkit.TestEventListener"]""")))  with WordSpecLikewith MustMatcherswith BeforeAndAfterAll {
  2. 现在我们已经订阅了EventStream,我们可以从测试用例中将其声明为:
    //4. Verifying log messages from eventStream"be verifiable via EventFilter in response to a QuoteRequest that is sent" in {val teacherRef = TestActorRef[TeacherLogActor]EventFilter.info(pattern = "QuoteResponse*", occurrences = 1) intercept {teacherRef ! QuoteRequest}}

EventFilter.info块仅截获1条以QuoteResponse( pattern='QuoteResponse* )开头的日志消息。 (您也可以通过使用start='QuoteResponse' 。如果没有消息发送给TeacherLogActor,则该测试用例将失败。

5 –使用构造函数参数测试Actor

请注意,我们在测试用例中创建Actor的方式是通过TestActorRef[TeacherLogActor]而不是通过system.actorOf 。 这只是为了使我们可以通过TeacherActorRef中的underlyingActor Actor方法访问Actor的内部。 我们将无法通过在常规运行时可以访问的ActorRef来实现此ActorRef 。 (这并没有给我们在生产中使用TestActorRef的任何借口。您会被追捕的)。

如果Actor接受参数,那么我们创建TestActorRef的方式将是:

val teacherRef = TestActorRef(new TeacherLogParameterActor(quotes))

整个测试用例将如下所示:

//5. have a quote list of the same size as the input parameter" have a quote list of the same size as the input parameter" in {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")val teacherRef = TestActorRef(new TeacherLogParameterActor(quotes))//val teacherRef = TestActorRef(Props(new TeacherLogParameterActor(quotes)))teacherRef.underlyingActor.quoteList must have size (4)EventFilter.info(pattern = "QuoteResponse*", occurrences = 1) intercept {teacherRef ! QuoteRequest}}

关闭ActorSystem

最后, afterAll生命周期方法:

override def afterAll() {  super.afterAll()system.shutdown()}

  • 与往常一样,可以从github这里下载整个项目。

翻译自: https://www.javacodegeeks.com/2014/10/akka-notes-actor-logging-and-testing.html

akka和rabbitmq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完数c++语言程序_C语言经典100题(19)

1上期答案揭晓首先给大家看看上一篇文章C语言经典100题(18)中第三部分编程题的答案&#xff1a;#includeint main(){ int s0,a,n,t; printf("请输入 a 和 n&#xff1a;\n"); scanf("%d%d",&a,&n); ta; while(n>0) { …

PHP怎样表示几时几分,PHP将时间戳转换为刚刚、N分钟前、今天几点几分、昨天几点几分......

自定义函数&#xff1a;<?php date_default_timezone_set(PRC); // 设置时区&#xff0c;如果已经设置可以删除function timeFormat( $timestamp ) {$curTime time();$space $curTime - $timestamp;if($space < 60) { // 一分钟以内$string "刚刚";return …

古巴:为生产做准备

“它可以在我的本地机器上运行&#xff01;” 如今&#xff0c;这听起来像模因&#xff0c;但仍然存在“开发环境与生产环境”的问题。 作为开发人员&#xff0c;您应始终牢记&#xff0c;您的应用程序有一天将在生产环境中开始运行。 在本文中&#xff0c;我们将讨论一些特定于…

php重载,PHP 重载

PHP 重载一个类中的方法与另一个方法同名&#xff0c;但是参数不同&#xff0c;这种方法称之为重载方法。很遗憾因为 PHP 是弱类型的语言&#xff0c; 所以在方法的参数中本身就可以接收不同类型的数据&#xff0c;又因为 PHP 的方法可以接收不定个数的参数&#xff0c;所以在 …

平板安装python_在CentOS上安装Python3的三种方法

Centos7默认自带了Python2.7版本,但是因为项目需要使用Python3.x你可以按照此文的三个方法进行安装.注&#xff1a;本文示例安装版本为Python3.5&#xff0c;一、Python源代码编译安装安装必要工具 yum-utils &#xff0c;它的功能是管理repository及扩展包的工具 (主要是针对r…

hibernate脏数据_Hibernate脏检查的剖析

hibernate脏数据介绍 持久性上下文使实体状态转换入队 &#xff0c;该实体状态转换在刷新后转换为数据库语句。 对于托管实体&#xff0c;Hibernate可以代表我们自动检测传入的更改并安排SQL UPDATE。 这种机制称为自动脏检查 。 默认的脏检查策略 默认情况下&#xff0c;Hibe…

python查询sql_Python处理SQL语句(提供SQL查询平台使用)

在搞公司的SQL查询(MySQL)平台时&#xff0c;需要对用户查询SQL进行条数限制&#xff0c;默认是在配置文件中配置一个“limit 1000”这样的参数。最自然想到的就是对用户通过web传入的SQL做处理&#xff0c;默认加上limit参数。这样一来就有这么几个问题需要处理&#xff1a;1…

php组成,php接口有几部分组成?

程序接口&#xff0c;由一套陈述、功能、选项、其它表达程序结构的形式、以及程序师使用的程序或者程序语言提供的数据组成PHP接口(interface)的特点1、接口的方法必须是公开的。2、接口的方法默认是抽象的&#xff0c;所以不在方法名前面加abstract。3、接口可以定义常量&…

AWS Elasticsearch后模式

因此&#xff0c;碰巧我们在SaaS版本的LogSentinel上遇到了生产问题–我们的Elasticsearch停止了对新数据编制索引。 由于Elasticsearch只是辅助存储&#xff0c;因此没有数据丢失&#xff0c;但这给我们的客户带来了一些问题&#xff08;他们无法在其仪表板上看到实时数据&…

python设置word背景色_Python数据可视化:WordCloud入门

WordCloud是一种很好的展现数据的方式&#xff0c;网上也有不少小工具和在线网页。但是有些不支持中文&#xff0c;有些安装复杂&#xff0c;所以决定用Python实现。主要参考官网&#xff0c;通过官网的例子&#xff0c;讲一下WordCloud的制作。主要流程获取内容的路径如果是一…

java 解析日期格式_日期/时间格式/解析,Java 8样式

java 解析日期格式自Java 几乎 开始以来&#xff0c;Java开发人员就通过java.util.Date类&#xff08;自JDK 1.0起&#xff09;和java.util.Calendar类&#xff08;自JDK 1.1起 &#xff09;来处理日期和时间。 在这段时间内&#xff0c;成千上万&#xff08;甚至数百万&#x…

php第三方登录代码,thinkPHP5项目中实现QQ第三方登录功能

本文实例讲述了thinkPHP5项目中实现QQ第三方登录功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a;最近用thinkPHP 5框架做了一个婚纱店的项目&#xff0c;在开发过程中需要用到第三方登录&#xff0c;腾讯官方给的案例是几个文件相互包含实现的&#xff0c;放到tp5…

mac 显示隐藏文件_如何在Mac上显示隐藏文件?苹果mac显示隐藏文件夹方法

与任何操作系统一样&#xff0c;macOS会将重要文件隐藏起来&#xff0c;以防止意外删除它们并因此而损坏系统。但是&#xff0c;在某些情况下&#xff0c;您可能需要在Mac上显示隐藏文件&#xff0c;例如&#xff0c;浏览“ 库”文件夹并清除旧日志&#xff0c;缓存或其他垃圾文…

分布式虚拟跟踪

跟踪提供了对系统的可见性&#xff0c;使开发人员和操作人员可以在运行时观察应用程序。 当系统不断增长并与更多微服务进行交互时&#xff0c;跟踪变得非常有价值。 在这样的环境中&#xff0c;这些痕迹非常棒&#xff0c;可以定位导致性能下降的故障和瓶颈。 在这篇文章中&a…

php 删除数组的空元素,php删除数组空元素的方法_后端开发

php如何实现自动跳转_后端开发php实现自动跳转的方法&#xff1a;1、通过php内置函数“header”&#xff0c;将http响应头中的“Location”设置为要跳转的URL即可&#xff1b;2、可以在javascript代码中将“window.location.href”指向要跳转的URL即可。php删除数组空元素的方法…

map for循环_JavaScript 用 for 循环太 low?你是不是有什么误解

天要吐槽下&#xff0c;我时不时地看到有些文章说“循环语句不好&#xff0c;你应该用 filter&#xff0c;map 和 reduce ”——每次看到有文章鼓吹&#xff0c;所有需要循环的场景一律用这几个函数式方法&#xff0c;我都恨得牙痒痒。没错&#xff0c;这些函数式方法确实有它们…

vue 动态组件组件复用_真正的动态声明性组件

vue 动态组件组件复用在这篇简短的文章中&#xff0c;我将重点介绍ADF动态声明性组件。 我的意思是一个众所周知的ADF标签af&#xff1a;declarativeComponent 。 它可以用作将页面设计为页面片段和组件组成的一种非常便捷的方法。 例如&#xff0c;我们的页面可以包含以下代码…

简单工程验收单表格_中铁超大型工程项目-123个精细化管理手册配套表格附件,超全...

中铁超大型工程项目-123个精细化管理手册配套表格附件&#xff0c;超全&#xff01;什么是项目精细化&#xff1f;答&#xff1a;工程项目精细化管理是一个系统的管理体系&#xff0c;包含一系列管理制度和办法&#xff0c;除了《工程项目精细化管理办法》这个纲领性文件外&…

php 执行 javascript,Bash/PHP/Javascript:如何运行输出javascript的php文件,并执行该javascript?...

目前我试图发送一个webhook请求来争执&#xff0c;所以我可以发送更新到我的资源库到我的不一致服务器中的一个频道。如果我在浏览器中加载页面&#xff0c;它会运行此代码&#xff0c;并且该消息将出现在我的不一致中&#xff1a;$(document).ready(function(){setTimeout(sen…

递归分解WAR文件

抽象 是否曾经需要分解WAR文件以及分解WAR文件中的所有JAR文件&#xff1f; 是的&#xff0c;我也是&#xff01; 我写了Ferris-war-exploder来爆炸&#xff1a; 一个JAR文件 一个WAR文件&#xff0c;它找到的每个JAR文件也会爆炸。 包含每个JAR文件&#xff08;请参阅&…