gpt4 book ai didi

multithreading - 用akka记录。应用程式设计

转载 作者:行者123 更新时间:2023-12-03 12:52:04 26 4
gpt4 key购买 nike

假设我有一个基于Futures,基于scala.concurrent的scala应用程序来处理异步/并发(到目前为止尚未使用任何参与者)。

在许多地方,我使用log4j将内容登录到日志文件中。
既然是I/O,我想我可以通过将日志消息发送到LoggingActor来提高性能。

像这样的东西:

def stuffTodo(arg:String)(implicit ex:ExecutionContext) : Future[Result] = {

// important performant work
// ..
logAcrot ! LogMessage("message-1")
// ...
}

其中消息: case class LogMessage(msg:String, implicit ex:ExecutionContext)
然后在 ActorLog
def receive = {
case LogMessage(msg:String, ex:ExecutionContext) ⇒ {log.info(msg + ex)}
}

我已经看到了其他方法,这些方法基本上是 包裹 scala.concurent.ExecutionContext(使用当前线程),并使用 Mapped Diagnostic Context -magic(log4j),并通过将线程ID附加到日志消息来进行日志记录。但是最终它会阻止/减慢线程/执行速度(据我所知),并使应用程序变慢。

在这种情况下,使用此Actor时,日志记录将保持独立/异步并同时保持顺序。

这样走是个好主意吗?分享经验故事?优点/缺点/问题?尝试重载之前要问..

最佳答案

Akka已经对日志记录提供了很好的支持,这在Logging - Akka Documentation页面上有记录。我认为没有必要或不需要在系统中创建logger actor,特别是在该机制已经存在的情况下。

您可能已经使用了LoggingAdaptor类来异步执行日志记录,它通过将其发布到事件总线上来实现此目的。您应该能够在参与者或外部使用相同的机制。

看看Logging.scala

记录Mixin

Scala有一个供actor使用的mixin,它为actor创建记录器并允许设置MDC。从文档中:

import Logging.MDC

final case class Req(work: String, visitorId: Int)

class MdcActorMixin extends Actor with akka.actor.DiagnosticActorLogging {
var reqId = 0

override def mdc(currentMessage: Any): MDC = {
reqId += 1
val always = Map("requestId" -> reqId)
val perMessage = currentMessage match {
case r: Req => Map("visitorId" -> r.visitorId)
case _ => Map()
}
always ++ perMessage
}

def receive: Receive = {
case r: Req => {
log.info(s"Starting new request: ${r.work}")
}
}
}

在 Actor 外登录

Logging.scala文件中,有两个在actor外部创建LoggingSource的示例:
trait MyType { // as an example
def name: String
}

implicit val myLogSourceType: LogSource[MyType] = new LogSource[MyType] {
def genString(a: MyType) = a.name
}

class MyClass extends MyType {
val log = Logging(eventStream, this) // will use "hallo" as logSource
def name = "hallo"
}

The second variant is used for including the actor system’s address:


 trait MyType { // as an example
def name: String
}

implicit val myLogSourceType: LogSource[MyType] = new LogSource[MyType] {
def genString(a: MyType) = a.name
def genString(a: MyType, s: ActorSystem) = a.name + "," + s
}

class MyClass extends MyType {
val sys = ActorSystem("sys")
val log = Logging(sys, this) // will use "hallo,akka://sys" as logSource
def name = "hallo"
}

如果需要,可以在日志适配器上设置MDC。

日志记录线程和MDC

当另一个线程异步执行日志记录时,文档还介绍了您在日志记录线程上的观点。

Since the logging is done asynchronously the thread in which the logging was performed is captured in Mapped Diagnostic Context (MDC) with attribute name sourceThread. With Logback the thread name is available with %X{sourceThread} specifier within the pattern layout configuration.

关于multithreading - 用akka记录。应用程式设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32491795/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com