我正在用Akka v2.5.23编写一个应用程序。该应用程序涉及以下参与者:
- 名为CalculatorRouter的路由器执行元类
- 名为Calculator的被路由者执行元类
我在创建Calculator actor时配置了一个PinnedDispatcher,并将log.info
放在这个actor类的receive方法中。我希望在日志文件中看到线程名称字段包含pinned
。但是,线程名称字段是default-dispatcher
。我在日志文件中搜索了一下,发现与此log.info
相关的所有线程名称都是default-dispatcher
。我的代码有什么问题吗?
日志文件片段:
09:49:25.116 [server-akka.actor.default-dispatcher-14] INFO handler.Calculator $anonfun$applyOrElse$3 92 - akka://server/user/device/$a/$a Total calc received
以下是代码片段:
class CalculatorRouter extends Actor with ActorLogging {
var router = {
val routees = Vector.fill(5) {
val r = context.actorOf(Props[Calculator].withDispatcher("calc.my-pinned-dispatcher"))
context.watch(r)
ActorRefRoutee(r)
}
Router(SmallestMailboxRoutingLogic(), routees)
}
def receive = {
case w: Calc => router.route(w, sender)
case Terminated(a) =>
router.removeRoutee(a)
val r = context.actorOf(Props[Calculator].withDispatcher("calc.my-pinned-dispatcher"))
context.watch(r)
router = router.addRoutee(r)
}
}
calc.my-pinned-dispatcher的配置如下:
calc.my-pinned-dispatcher {
executor="thread-pool-executor"
type=PinnedDispatcher
}
类计算器的源代码如下:
class Calculator extends Actor with ActorLogging {
val w = new UdanRemoteCalculateTotalBalanceTime
def receive = {
case TotalCalc(fn, ocvFilepath, ratedCapacity, battCount) ⇒
log.info(s"${self.path} Total calc received")
Try{
w.CalculateTotalBalanceTime(1, fn, ocvFilepath, ratedCapacity)
} match {
case Success(t) ⇒
val v = t.getIntData
sender.!(Calculated(v))(context.parent)
case Failure(e) ⇒ log.error(e.getMessage)
}
}
}
object Calculator {
sealed trait Calc
final case class TotalCalc(filename: String, ocvFilepath: String, ratedCapacity: String, batteryCount: Int) extends Calc
}
logback.xml
<configuration debug="true">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<!-- reset all previous level configurations of all j.u.l. loggers -->
<resetJUL>true</resetJUL>
</contextListener>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/app.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>/var/log/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>100</maxHistory>
<totalSizeCap>30000MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M %L - %msg%n</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
<queueSize>500</queueSize>
<includeCallerData>true</includeCallerData>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M %L - %msg%n</pattern>
</encoder>
</appender>
<logger name="application" level="DEBUG"/>
<root level="INFo">
<appender-ref ref="ASYNCFILE"/>
</root>
</configuration>
'20 3月4日更新
在我把akka.loggers-dispatcher = "calc.my-pinned-dispatcher"
放到conf文件中之后,我在日志文件的每一行都得到了my-pinned-dispatcher-xx
作为线程名。我认为线程名应该指示actor Calculator的receive
方法正在执行的线程,在本例中,类似于'pinned-dispatcher-xx'
的东西,因为线程是根据我的配置由固定的调度程序获得的。现在它证明了它指示了由记录器的调度程序获得的线程。如果是这种情况,如何为参与者的消息处理程序代码记录线程名称?
1条答案
按热度按时间f5emj3cl1#
我认为解决方案是在
application.conf
中添加akka.loggers-dispatcher
如果你在akka的default configuration中搜索
logger-dispatcher
,你会发现值是“akka.actor.default-dispatcher”,我们需要如上所示覆盖这个配置。编辑
ActorLogging是异步的。当您使用ActorLogging进行记录时,它会将消息传送至记录执行元,而该执行元预设会在预设分派程式上执行。Logback会记录呼叫它的执行绪,而该执行绪将是ActorLogging执行元的执行绪,而不是您的执行元的执行绪。为了达成此目的,有一个所谓的Map诊断上下文(MDC),可撷取
akka source
(执行日志记录的执行元的路径)、**source thread
(执行日志记录的线程)**以及执行日志记录的更多内容。如文档中所示:
由于日志记录是异步完成的,因此在MDC中使用属性名称
sourceThread
捕获执行日志记录的线程。执行日志记录的参与者的路径在MDC中可用,属性名为
akkaSource
。执行日志记录的执行元系统名称在MDC中可用,其属性名称为
sourceActorSystem
,但通常也包含在akkaSource
属性中。执行元系统的地址(如果系统使用集群,则包含主机和端口)可通过
akkaAddress
获得。对于类型化的参与者,日志事件时间戳是在进行日志调用时获取的,但是对于Akka的内部日志记录以及经典的参与者日志记录是异步的,这意味着日志条目的时间戳是在调用底层日志记录器实现时获取的,这一点一开始可能会令人惊讶。如果您想更准确地输出此类日志记录器的时间戳,请使用MDC属性
akkaTimestamp
。请注意,MDC键对于类型化的参与者将没有任何值。如果有帮助的话,让我知道!!