我正在尝试akka流,但我无法通过我的简单示例获得背压。我很遗憾没有经历过akka(溪流),所以可能我错过了一些大事。
我生产(提供队列)整数比消耗它们更快,所以我认为背压会开始。 我的目标是始终使用放入队列中的最新项目(这就是为什么我有bufferSize = 1和 源队列上的OverflowStrategy.dropHead()。
public class SimpleStream {
public static void main(String[] argv) throws InterruptedException {
final ActorSystem system = ActorSystem.create("akka-streams");
final Materializer materializer = ActorMaterializer.create(system);
final Procedure<Integer> slowConsumer = (i) -> {
System.out.println("consuming [" + i + "]");
ThreadUtils.sleepQuietly(1000, TimeUnit.MILLISECONDS);
};
final SourceQueue<Integer> q = Sink
.<Integer>foreach(slowConsumer)
.runWith(Source.<Integer>queue(1, OverflowStrategy.dropHead()), materializer);
final AtomicInteger i = new AtomicInteger(0);
final Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
int n = i.incrementAndGet();
q.offer(n);
System.out.println("produced: [" + n + "]");
ThreadUtils.sleepQuietly(500, TimeUnit.MILLISECONDS);
}
});
t.setName("ticking");
t.start();
// run some time... to observe the effects.
ThreadUtils.sleepQuietly(1, TimeUnit.HOURS);
t.interrupt();
t.join();
// eventually shutdown akka here...
}
}
然而这是结果:
produced: [1]
consuming [1]
produced: [2]
produced: [3]
consuming [2] <-- Expected to be consuming 3 here.
produced: [4]
produced: [5]
consuming [3] <-- Expected to be consuming 5 here.
produced: [6]
produced: [7]
请忽略此处的线程内容,只是假冒从外部获取数据 来源(如果我必须在实际项目中使用它,就会发生这种情况)。
知道我缺少什么吗?
答案 0 :(得分:0)
Source.queue
终止背压的信号。这就是Source.queue方法接受OverflowStrategy
的原因。如果可以在队列的上游发信号通知背压,那么就不需要处理队列可能溢出的情况。但由于背压不会传播到队列之外,因此需要定义策略来处理比消费者更快的生产者。
对于典型的流,最终Source
会从Sink
收到需求以产生更多结果。但是,使用从Source.queue
创建的流,“最终源”是队列。如果有的话,这个队列只能排出内容。它不能向上游发出信号以产生更多结果,因为上游位于offer
方法的另一侧。