Scala 播放历史数据Akka流

Scala 播放历史数据Akka流,scala,akka-stream,Scala,Akka Stream,是否可以根据定义的时钟和Akka流发送数据?或者他们只是在数据到达时释放出压力?我特别想知道,是否有可能使用Source.tick,通过模拟时钟播放历史数据。这取决于定义的时钟是什么意思 实际壁时间 正如您提到的Source.tick是从系统时钟获取实际时间时钟的一种可能性。问题在于,接收器可能不会以大于或等于源产生滴答声的间隔的速率发出需求信号。例如,您的接收器可能每分钟仅发出一次请求信号,但Source.tick中的间隔可能为10秒。在这种情况下,将从文档中删除5个中间记号: 如果消费者在以

是否可以根据定义的时钟和Akka流发送数据?或者他们只是在数据到达时释放出压力?我特别想知道,是否有可能使用Source.tick,通过模拟时钟播放历史数据。

这取决于定义的时钟是什么意思

实际壁时间

正如您提到的Source.tick是从系统时钟获取实际时间时钟的一种可能性。问题在于,接收器可能不会以大于或等于源产生滴答声的间隔的速率发出需求信号。例如,您的接收器可能每分钟仅发出一次请求信号,但Source.tick中的间隔可能为10秒。在这种情况下,将从文档中删除5个中间记号:

如果消费者在以下时间点未请求任何元素: 生成勾号元素后,它将不会接收该勾号元素 稍后

模拟时间

始终可以使用源来模拟时间

我们可以首先创建一个函数,该函数将使用开始时间、结束时间和间隔来模拟时钟:

type MillisFromEpoch = Long

type MillisInterval = Long


val clock : (MillisFromEpoch, MillisFromEpoch, MillisInterval) => () => Iterator[MillisFromEpoch] = 
  (startTime, stopTime, interval) => () => new Iterator[MillisFromEpoch] {
    var currentTime = startTime

    override def hasNext : Boolean = currentTime < stopTime

    override def next() : MillisFromEpoch = {
      val returnMilis = currentTime
      currentTime += interval

      return returnMillis
    }
  }
或者我们可以创建一个时钟,从现在开始,以5秒的间隔递增60秒结束:

val now : MillisFromEpoch = System.currentTimeMillis()

val simulatedClockFromNowSource : Source[MillisFromEpoch,_] = 
  Source fromIterator clock(now, now + 60*second, 5*second)
采样频率

有一种方法可以使用Source.tick,即使下游消费者的速度低于Source指定的tick间隔。我们可以创建一个Flow.filter,它不断地向源发送需求信号,但只通过定义的增量时间

我们可以从一个函数开始,该函数使用一个内部变量跟踪时间间隔:

val frequencySample : (MillisInterval) => (MillisFromEpoch) => Boolean = 
  (interval) => {

    var lastValidTime : MillisFromEpoch = -1

    (timeToCheck) => {
      if(lastValidTime < 0 || timeToCheck >= lastValidTime + interval) {
        lastValidTime = timeToCheck

        true
      }
      else {
        false
      }
    }
  }
现在,我们可以创建一个频率较低(例如10秒)的流,该流连接到频率较高(例如1秒)的源:

val slowFrequency : MillisInterval = 10 * second

//simulatedClockFromEpoch ticks every 1 second
//frequnencySampleFlow only passes every 10 second tick through
val slowSource = 
  simulatedClockFromEpochSource via frequencySampleFlow(slowFrequency)

你自己已经试过什么了?我以前也构建过这个系统的其他版本,只是没有流媒体框架。对于流式传输,时钟似乎应该是一个源,而数据源则是监听时钟以确定何时发出数据的流。在我构建的系统中,时钟更像是触发流计算的接收器。这是一个非常有用的答案,谢谢。有了这个模拟时钟,历史数据源就会监听滴答声,以知道何时发出滴答声。也许超出了这个问题的范围:我还想知道,如果依赖于源的流仅依赖于数据的一个子集,频率低于可用频率,或者仅针对整个历史的一个子集,那么依赖于源的流如何指示要发出哪些数据。这样的流可能会忽略它不感兴趣的数据,但如果数据不是真正需要的话,则流式传输数据的效率会很低。@fwc不客气。我已经更新了我的答案,以解决您评论中的问题。
val frequencySampleFlow : (MillisInterval) => Flow[MillisFromEpoch, MillisFromEpoch, _] =
  (frequency) => Flow[MillisFromEpoch]  filter frequencySample(frequency)
val slowFrequency : MillisInterval = 10 * second

//simulatedClockFromEpoch ticks every 1 second
//frequnencySampleFlow only passes every 10 second tick through
val slowSource = 
  simulatedClockFromEpochSource via frequencySampleFlow(slowFrequency)