Scala 如何在不增加延迟的情况下为monix中的每个任务添加固定延迟
我正在使用monix使用卡夫卡的消息 我想在从主题中读取消息10秒后处理该消息 10秒-分钟的延迟不应阻止读取更多消息 我尝试使用下面的代码测试这种行为,使用Task.delayExecution延迟10秒 我还尝试了Scala 如何在不增加延迟的情况下为monix中的每个任务添加固定延迟,scala,apache-kafka,kafka-consumer-api,apache-kafka-streams,monix,Scala,Apache Kafka,Kafka Consumer Api,Apache Kafka Streams,Monix,我正在使用monix使用卡夫卡的消息 我想在从主题中读取消息10秒后处理该消息 10秒-分钟的延迟不应阻止读取更多消息 我尝试使用下面的代码测试这种行为,使用Task.delayExecution延迟10秒 我还尝试了Observable.delayOnExecution和Observable.delayonext import monix.eval.Task import monix.reactive.Observable object TestApp extends App { imp
Observable.delayOnExecution
和Observable.delayonext
import monix.eval.Task
import monix.reactive.Observable
object TestApp extends App {
import java.util.Date
case class SomeClass(
value: Int, consumingDate: Date,
handlerExecutionDate: Date = null
)
import scala.concurrent.duration._
import scala.concurrent.Await
import monix.execution.Scheduler.Implicits.global
val res = Observable.fromIterable((1 to 100).map(i => SomeClass(value = i, consumingDate = new Date)))
.mapEval(i =>
Task.delay(
SomeClass(
value = i.value,
consumingDate = i.consumingDate
)
).delayExecution(10 seconds)
)
.foreachL{ x =>
val r = SomeClass(
x.value,
x.consumingDate,
new Date()
)
println(r)
}.runToFuture
Await.result(res, 100.seconds)
}
但是上面的代码为每条消息增加了延迟。第一条消息延迟10秒,但第二条消息延迟20秒,第三条消息延迟30秒,依此类推
使用monix可以做类似的事情吗
我正在考虑其他替代基于monix的解决方案,比如使用内存队列。消费者将继续排队,直到达到其限制,然后
更新:
我使用Task.eval().restartutil()找到了一个解决方案
添加下面的代码
package com.agoda.cusco.campaign.data.collector.consumer
import monix.eval.Task
import monix.reactive.Observable
object TestApp extends App {
import java.util.Date
case class SomeClass(
value: Int, consumingDate: Date,
handlerExecutionDate: Date = null
)
import scala.concurrent.duration._
import scala.concurrent.Await
import monix.execution.Scheduler.Implicits.global
val res = Observable.fromIterable((1 to 100).map(i => SomeClass(value = i, consumingDate = new Date(System.currentTimeMillis + i*100))))
.mapEval(message =>
Task.eval(new Date()).restartUntil(currentTime => (currentTime.getSeconds - message.consumingDate.getSeconds) > 10).map(_ => message)
)
.foreachL{ x =>
val r = SomeClass(
x.value,
x.consumingDate,
new Date()
)
println(r)
}.runToFuture
Await.result(res, 100.seconds)
}
我不完全确定它是否是理想的解决方案,因为它似乎正在进行活动CPU计算以使其工作
希望检查是否有更好的替代方案。无法重现您的问题。我试着运行你的代码,它每10秒打印一行日期和时间,你确定你有如此多的延迟吗?是的,你是对的,打印的差异实际上是10秒。但是它仍然在增加延迟,因为事件/消息都是在Observable.fromIterable(1到100)
中同时生成的,但是每个消息的打印都有10秒的延迟。我将更新代码,使其更清楚地表示问题。如果出于技术原因,听起来像是设计问题。如果这是一个产品需求,那么我想这是一个解决方案。在卡夫卡的记忆中排队通常是一种反模式。每个分区都是一个队列。消费者应该尽其所能消费。否则,需要编写逻辑来处理缓冲区溢出,在实例崩溃或重新启动时丢失内存中的消息。通过手动偏移提交,您可以克服邮件丢失的问题。实时处理通常需要在缓冲区溢出时丢弃消息,当处理速度跟不上传入速率时,必须丢弃消息。