[英]Akka Stream TCP + Akka Stream Kafka producer not stopping not publishing messages and not error-ing out
我有以下流:
Source(IndexedSeq(ByteString.empty))
.via(
Tcp().outgoingConnection(bsAddress, bsPort)
.via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
.map(_.utf8String)
)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
Producer.plainSink(
ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
.withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
)
).onComplete {
case Success(Done) => printAndByeBye("Stream ends successfully")
case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
}
它工作正常一段時間,我可以使用填充在Kafka主題上的消息。 但有時候,顯然是在一個隨機的間隔,沒有更多的消息發布,這個代碼沒有記錄任何錯誤(printAndByeBye將打印傳遞的消息並終止actor系統。)重新啟動應用程序后,消息繼續流。
關於如何知道這里發生了什么的任何想法?
編輯:我把Kamon放在上面,我可以看到以下行為:
它看起來像是在沒有通知流應該停止的情況下停止了,但我不知道如何使其顯式並停止流。
我建議用監督屬性創建流程來處理TCP連接中可能的異常,如:
val flow =
Tcp().outgoingConnection("", 12)
.via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
.map(_.utf8String).withAttributes(ActorAttributes.supervisionStrategy {
case ex: Throwable =>
println("Error ocurred: " + ex)
Supervision.Resume
}
和
Source(IndexedSeq(ByteString.empty))
.via(flow)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
Producer.plainSink(
ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
.withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
)
).onComplete {
case Success(Done) => printAndByeBye("Stream ends successfully")
case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
}
如果流有任何錯誤,則流停止。 使用此配置,您將查看流是否已拋出任何異常。
如果一切都變得沉默, 可能會在某個地方應用背壓。 嘗試並選擇性地更換具有非背壓感知階段的背壓感知階段,並檢查問題是否仍然存在。 在您的情況下,有兩種可能的背壓源:
1)TCP連接
您可以嘗試將無限的ByteString
源附加到Kafka,執行以下操作:
Source.cycle(() => List(???).iterator)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
Producer.plainSink(
ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
.withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
)
).onComplete {
case Success(Done) => printAndByeBye("Stream ends successfully")
case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
}
2)卡夫卡水槽
用一些日志記錄替換它
Source(IndexedSeq(ByteString.empty))
.via(
Tcp().outgoingConnection(bsAddress, bsPort)
.via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
.map(_.utf8String)
)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runForeach(println)
.onComplete {
case Success(Done) => printAndByeBye("Stream ends successfully")
case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
}
你能在2個案例中只有一個看到問題嗎? 同時? 沒有?
流沒有失敗,但是TCP流空閑,因為設備發布數據在一段時間后停止發送數據而不丟棄連接。 而不是使用更簡單:
TCP().outgoingConnection(bsAddress, bsPort)
我最終使用:
def outgoingConnection(
remoteAddress: InetSocketAddress,
localAddress: Option[InetSocketAddress] = None,
options: immutable.Traversable[SocketOption] = Nil,
halfClose: Boolean = true,
connectTimeout: Duration = Duration.Inf,
idleTimeout: Duration = Duration.Inf): Flow[ByteString, ByteString, Future[OutgoingConnection]] = ???
所以
Tcp().outgoingConnection(bsAddress, bsPort)
成為
val connectTimeout: Duration = 1 second
val idleTimeout: Duration = 2 second
Tcp().outgoingConnection(
remoteAddress = InetSocketAddress.createUnresolved(bsAddress, bsPort),
connectTimeout = connectTimeout,
idleTimeout = idleTimeout
)
通過通知idleTimeout,跟隨啟動失敗,可以重新啟動另一個流程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.