如何使用Akka Stream限制图形中的请求?

时间:2019-01-09 09:23:07

标签: java akka buffer akka-stream

背景

我有一个项目,我们在Java中使用akka流。

在这个项目中,我有一个字符串流和一个对它们进行一些操作的图形。

客观

在我的图表中,我想将该流广播给2个工作人员。一个人将用'a'替换所有字符'A',并在实时接收数据时发送数据。

另一个将接收数据,每3个字符串将连接这3个字符串并将它们映射为数字。

如下所示:

akka-streams-buffer

很显然,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

??

1 个答案:

答案 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