【发布时间】:2018-03-21 20:24:20
【问题描述】:
我有一个应用程序,它需要一些非常大的分隔文件(约 10 到 15 M 记录)并在进行一些预处理后将其摄取到 Kafka 中。作为此预处理的一部分,我们将分隔记录转换为 json 并将元数据添加到该 json 消息(文件名、行号)。我们使用 Json4s Native 序列化器来做这件事,如下所示:
import org.json4s.native.Serialization._
//some more code and below is the final output.
write(Map(
"schema" -> schemaName,
"data" -> List(resultMap),
"flag" -> "I")
)
将消息转换为 Json 后,我们会添加消息元数据,例如:
def addMetadata(msg: String, metadata: MessageMetadata): String = {
val meta = write(asJsonObject(metadata))
val strippedMeta = meta.substring(1, meta.length -1)
val strippedMessage = msg.substring(1, msg.lastIndexOf("}"))
"{" + strippedMessage + "," + strippedMeta + "}"
msg
}
最后的消息看起来像这样:
{"schema":"SchemaName"
"data": [
],
"flag": "I",
"metadata":{"srcType":"file","fileName":"file","line":1021}}
现在这两种方法都在泄漏一些内存并抛出错误。该应用程序具有每分钟处理 300k 条消息的能力,但在大约 4-5 分钟后它会变慢并最终死亡。我知道字符串连接会产生很多垃圾对象,想知道最好的方法是什么?
java.lang.OutOfMemoryError: 超出 GC 开销限制
【问题讨论】:
-
即使字符串连接在这里和那里分配了一些不必要的字符缓冲区,它也不应该在一天结束时泄漏任何东西。如果您的应用程序流血而死,原因可能在其他地方。你可能会觉得this 至少很有趣...
标签: java scala performance garbage-collection