我有一个项目,我们在Java中使用akka流。
在这个项目中,我有一个字符串流和一个对它们进行一些操作的图形。
在我的图表中,我想将该流广播给2个工作人员。一个人将用'a'
替换所有字符'A'
,并在实时接收数据时发送数据。
另一个将接收数据,每3个字符串将连接这3个字符串并将它们映射为数字。
如下所示:
很显然,Sink 2
不会像Sink 1
那样接收信息。但这是预期的行为。有趣的部分是工人2。
做工人1很容易,但并不难。这里的问题在做工作者2。我知道akka具有可以保存多达X条消息的缓冲区,但是看起来我不得不选择现有的Overflow strategies中的一个,这常常导致选择我要选择的消息或是否要让流保持活动状态。
我想要做的就是,当worke2中的缓冲区达到缓冲区的最大大小时,对其所拥有的所有消息执行concat和map操作,然后将它们发送(在之后重新设置缓冲区)。
但是即使阅读了stream-rate关于akka的文档,我也找不到一种方法,至少是使用Java。
我也检查了一个类似的问题,Selective request-throttling using akka-http stream,但是已经过去一年多了,没有人回应。
使用图形DSL,我将如何从以下路径创建路径:
源-> bcast-> worker2->接收器2
??
答案 0 :(得分:1)
在bcast
之后应用groupedWithin
运算符,其持续时间不受限制,并且元素数设置为3。
https://doc.akka.io/docs/akka/2.5/stream/operators/Source-or-Flow/groupedWithin.html
您也可以自己做,添加一个阶段将元素存储在List
中,并在到达3个元素时发出列表。
import akka.stream.Attributes;
import akka.stream.FlowShape;
import akka.stream.Inlet;
import akka.stream.Outlet;
import akka.stream.stage.AbstractInHandler;
import akka.stream.stage.GraphStage;
import akka.stream.stage.GraphStageLogic;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
public class RecordGrouper<T> extends GraphStage<FlowShape<T, List<T>>> {
private final Inlet<T> inlet = Inlet.create("in");
private final Outlet<List<T>> outlet = Outlet.create("out");
private final FlowShape<T, List<T>> shape = new FlowShape<>(inlet, outlet);
@Override
public GraphStageLogic createLogic(Attributes inheritedAttributes) {
return new GraphStageLogic(shape) {
List<T> batch = new ArrayList<>(3);
{
setHandler(
inlet,
new AbstractInHandler() {
@Override
public void onPush() {
T record = grab(inlet);
batch.add(record);
if (batch.size() == 3) {
emit(outlet, ImmutableList.copyOf(batch));
batch.clear();
}
pull(inlet);
}
});
}
@Override
public void preStart() {
pull(inlet);
}
};
}
@Override
public FlowShape<T, List<T>> shape() {
return shape;
}
}
作为副节点,我认为buffer
运算符不会起作用,因为它仅在出现反压时才起作用。因此,如果一切都很安静,则元素仍将一一发射,而不是三到三发射。https://doc.akka.io/docs/akka/2.5/stream/operators/Source-or-Flow/buffer.html