akka和rabbitmq_Akka Notes –演员记录和测试
akka和rabbitmq
在前兩部分( 一 , 二 )中,我們簡(jiǎn)要討論了Actor以及消息傳遞的工作方式。 在這一部分中,讓我們看一下如何修復(fù)并記錄我們的TeacherActor 。
回顧
這就是我們上一部分中的Actor的樣子:
使用SLF4J記錄Akka
您會(huì)注意到,在代碼中,我們正在將quoteResponse打印到標(biāo)準(zhǔn)輸出,您顯然同意這是一個(gè)壞主意。 讓我們通過(guò)SLF4J Facade啟用日志記錄來(lái)解決此問(wèn)題。
1.修復(fù)類(lèi)以使用日志記錄
Akka提供了一個(gè)很好的小特征ActorLogging來(lái)實(shí)現(xiàn)它。 讓我們混合:
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}繞道而行:
在內(nèi)部,當(dāng)我們記錄一條消息時(shí),ActorLogging中的記錄方法(最終)將日志消息發(fā)布到EventStream 。 是的,我確實(shí)說(shuō)過(guò)publish 。 那么,EventStream實(shí)際上是什么?
EventStream和記錄
EventStream行為就像可以向其發(fā)布和接收消息的消息代理一樣。 與常規(guī)MOM的一個(gè)細(xì)微區(qū)別是EventStream的訂閱者只能是Actor。
在記錄消息的情況下,所有日志消息都將發(fā)布到EventStream。 默認(rèn)情況下,訂閱這些消息的Actor是DefaultLogger ,它僅將消息打印到標(biāo)準(zhǔn)輸出中。
class DefaultLogger extends Actor with StdOutLogger { override def receive: Receive = {...case event: LogEvent ? print(event)} }因此,這就是我們嘗試啟動(dòng)StudentSimulatorApp的原因,我們看到寫(xiě)入控制臺(tái)的日志消息。
也就是說(shuō),Eve??ntStream不僅適合于記錄。 它是VM內(nèi)ActorWorld內(nèi)部可用的通用發(fā)布-訂閱機(jī)制(稍后會(huì)詳細(xì)介紹)。
返回SLF4J設(shè)置:
2.將Akka配置為使用SLF4J
akka{ loggers = ["akka.event.slf4j.Slf4jLogger"]loglevel = "DEBUG"logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" }我們將此信息存儲(chǔ)在名為application.conf的文件中,該文件應(yīng)位于您的類(lèi)路徑中。 在我們的sbt文件夾結(jié)構(gòu)中,我們將其放在您的main/resources目錄中。
從配置中,我們可以得出:
但是,為什么前面的示例沒(méi)有提供application.conf?
僅僅是因?yàn)锳kka提供了一些合理的默認(rèn)值,所以我們?cè)陂_(kāi)始使用它之前不需要構(gòu)建配置文件。 為了自定義各種內(nèi)容,我們將在此頻繁地重新訪問(wèn)此文件。 您可以在application.conf內(nèi)部使用一堆很棒的參數(shù)來(lái)單獨(dú)記錄日志。 它們?cè)谶@里詳細(xì)解釋。
3.放入logback.xml
現(xiàn)在,我們將配置一個(gè)由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文件夾中。 請(qǐng)確保main/resources現(xiàn)在位于eclipse或其他IDE的類(lèi)路徑中。 還應(yīng)將logback和slf4j-api包含到build.sbt中 。
而當(dāng)我們揭開(kāi)序幕我們StudentSimulatorApp和發(fā)送郵件到我們的新TeacherLogActor ,該akkaxxxxx.log文件,我們配置看起來(lái)像這樣。
測(cè)試Akka
請(qǐng)注意,這絕不是Test Akka的詳盡介紹。 我們將在以下各部分中相應(yīng)標(biāo)題下的“測(cè)試”的更多功能上構(gòu)建測(cè)試。 這些測(cè)試用例旨在覆蓋我們之前編寫(xiě)的Actor。
當(dāng)StudentSimulatorApp我們的需求時(shí),您將同意應(yīng)將其從測(cè)試用例中刪除。
為了減輕測(cè)試的痛苦,Akka提出了一個(gè)了不起的測(cè)試工具包,使用它我們可以做一些神奇的事情,例如直接探查Actor實(shí)現(xiàn)的內(nèi)部。
聊夠了,讓我們看看測(cè)試用例。
首先讓我們嘗試將StudentSimulatorApp映射到測(cè)試用例。
現(xiàn)在讓我們單獨(dú)看一下聲明。
class TeacherPreTest extends TestKit(ActorSystem("UniversityMessageSystem")) with WordSpecLikewith MustMatcherswith BeforeAndAfterAll {因此,從TestCase類(lèi)的定義中,我們看到:
1、2 –向演員發(fā)送消息
3 –維護(hù)參與者的內(nèi)部狀態(tài)
第三種情況使用TestActorRef的underlyingActor quoteList方法,并調(diào)用TeacherActor的quoteList方法。 quoteList方法返回引號(hào)列表。 我們使用此列表來(lái)聲明其大小。
如果對(duì)quoteList引用使您退縮,請(qǐng)參考上面列出的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部分(上文)中討論的那樣,所有日志消息都進(jìn)入EventStream ,并且SLF4JLogger訂閱并使用其附加程序?qū)⑵鋵?xiě)入日志文件/控制臺(tái)等。直接在我們的測(cè)試用例中使用EventStream并斷言日志消息本身的存在? 看起來(lái)我們也可以做到。
這涉及兩個(gè)步驟:
EventFilter.info塊僅截獲1條以QuoteResponse( pattern='QuoteResponse* )開(kāi)頭的日志消息。 (您也可以通過(guò)使用start='QuoteResponse' 。如果沒(méi)有消息發(fā)送給TeacherLogActor,則該測(cè)試用例將失敗。
5 –使用構(gòu)造函數(shù)參數(shù)測(cè)試Actor
請(qǐng)注意,我們?cè)跍y(cè)試用例中創(chuàng)建Actor的方式是通過(guò)TestActorRef[TeacherLogActor]而不是通過(guò)system.actorOf 。 這只是為了使我們可以通過(guò)TeacherActorRef中的underlyingActor Actor方法訪問(wèn)Actor的內(nèi)部。 我們將無(wú)法通過(guò)在常規(guī)運(yùn)行時(shí)可以訪問(wèn)的ActorRef來(lái)實(shí)現(xiàn)此ActorRef 。 (這并沒(méi)有給我們?cè)谏a(chǎn)中使用TestActorRef的任何借口。您會(huì)被追捕的)。
如果Actor接受參數(shù),那么我們創(chuàng)建TestActorRef的方式將是:
val teacherRef = TestActorRef(new TeacherLogParameterActor(quotes))整個(gè)測(cè)試用例將如下所示:
//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}}關(guān)閉ActorSystem
最后, afterAll生命周期方法:
override def afterAll() { super.afterAll()system.shutdown()}碼
- 與往常一樣,可以從github這里下載整個(gè)項(xiàng)目。
翻譯自: https://www.javacodegeeks.com/2014/10/akka-notes-actor-logging-and-testing.html
akka和rabbitmq
總結(jié)
以上是生活随笔為你收集整理的akka和rabbitmq_Akka Notes –演员记录和测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 处理Java异常的10种最佳实践
- 下一篇: 古巴:为生产做准备