在Flink任务实例内部,我需要在事件发生时访问远程Web服务以获取一些数据,但是我不想每次事件发生时都访问远程Web服务,因此我需要将数据缓存在本地内存中并且可以访问该过程的所有任务,该怎么做?将数据存储在类级别的静态私有变量中?
如以下示例所示,如果在类Splitter上设置了局部变量localCache,则它将在操作员级别而不是进程级别进行缓存。
public class WindowWordCount {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Tuple2<String, Integer>> dataStream = env
.socketTextStream("localhost", 9999)
.flatMap(new Splitter())
.keyBy(0)
.timeWindow(Time.seconds(5))
.sum(1);
dataStream.print();
env.execute("Window WordCount");
}
public static class Splitter implements FlatMapFunction<String, Tuple2<String, Integer>> {
***private object localCache ;***
@Override
public void flatMap(String sentence, Collector<Tuple2<String, Integer>> out) throws Exception {
for (String word: sentence.split(" ")) {
out.collect(new Tuple2<String, Integer>(word, 1));
}
}
}
}
答案 0 :(得分:0)
就像你说的那样。您将在RichFlatMapFunction
中使用静态变量,然后在open
中对其进行初始化。在送入任何记录之前,将在每个TaskManager上调用open
。请注意,有一个为每个不同插槽创建的Splitter实例,因此在大多数情况下,一个TaskManager上有多个Splitter实例。因此,您需要防止双重创建。
public static class Splitter implements FlatMapFunction<String, Tuple2<String, Integer>> {
private transient Object localCache;
@Override
public void open(Configuration parameters) throws Exception {
if (localCache == null)
localCache = ... ;
}
@Override
public void flatMap(String sentence, Collector<Tuple2<String, Integer>> out) throws Exception {
for (String word: sentence.split(" ")) {
out.collect(new Tuple2<String, Integer>(word, 1));
}
}
}
答案 1 :(得分:0)
一种可伸缩的方法可能使用Source运算符实际执行对Web服务的调用,然后将结果写入流中。然后,您可以将该流作为广播流访问给操作员,从而将广播流发出的一个对象(Web调用结果)发送给接收操作员的每个实例。这将在集群中的所有机器和JVM之间共享该单个Web调用的结果。您还可以保留广播状态,并在集群扩展时与操作员的新实例共享它。