是否可以根据Akka Streams定义的时钟发出数据?或者他们只是在数据到达时发出(忽略背压)?我特别想知道是否可以使用“模拟”时钟回放历史数据,或许可以使用Source.tick
。
答案 0 :(得分:1)
这取决于“定义时钟”的含义。
实际停电时间
正如您所提到的,Source.tick
是一种从系统时钟获取实际时间的可能性。问题是Sink
可能不会以大于或等于Source生成滴答的间隔的速率发出需求信号。例如,您的接收器可能每分钟仅发出一次请求信号,但您在Source.tick中的间隔可能是10 seconds
。在这种情况下,将从文档中删除5个中间刻度:
如果消费者在某个时间点没有请求任何元素 生成tick元素,它将不会接收该tick元素 后面。
模拟时间
始终可以使用Source
来模拟时间。
我们可以先创建一个使用开始时间,结束时间和间隔来模拟时钟的函数:
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
}
}
此时钟现在可以为源提供信号。作为一个例子,我们可以创建一个从unix epoch开始并以1秒递增直到时间结束的时钟:
val epoch : MillisFromEpoch = 0L
val second : MillisInterval = 1000L
val simulatedClockFromEpochSource : Source[MillisFromEpoch,_] =
Source fromIterator clock(epoch, Long.MaxValue, 1*second)
或者我们可以创建一个现在开始的时钟,并在60秒内以5秒的间隔递增:
val now : MillisFromEpoch = System.currentTimeMillis()
val simulatedClockFromNowSource : Source[MillisFromEpoch,_] =
Source fromIterator clock(now, now + 60*second, 5*second)
采样频率
即使下游消费者比源指定的滴答间隔慢,也可以使用Source.tick。我们可以创建一个Flow.filter
,它不断地向Source发出需求信号,但只会传递相隔定义的增量的时间。
我们可以从一个使用内部变量跟踪时间间隔的函数开始:
val frequencySample : (MillisInterval) => (MillisFromEpoch) => Boolean =
(interval) => {
var lastValidTime : MillisFromEpoch = -1
(timeToCheck) => {
if(lastValidTime < 0 || timeToCheck >= lastValidTime + interval) {
lastValidTime = timeToCheck
true
}
else {
false
}
}
}
现在这个函数可以用来创建Flow:
val frequencySampleFlow : (MillisInterval) => Flow[MillisFromEpoch, MillisFromEpoch, _] =
(frequency) => Flow[MillisFromEpoch] filter frequencySample(frequency)
现在我们可以创建一个具有较慢频率(例如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)