O caso de uso AggregatingState de gerenciamento de estado com chave para encontrar o valor médio
Série de artigos
Tutorial Flink (13) Gerenciamento de estado de estado com chave ValueState usando alarme de diferença de temperatura
Tutorial de Flink (14) caso de uso de MapState de gerenciamento de estado com chave
Tutorial de Flink (15) gerenciamento de estado de estado com chave ListState usando ValueState para implementar
tutorial de Flink (16) estado de estado com chave The ReducingState caso de uso de gerenciamento para encontrar o valor máximo
Flink tutorial (17) O caso de uso AggregatingState de gerenciamento de estado com chave para encontrar o valor médio
Um, o método de AggregatingState
- AggregatingState precisa ser usado em conjunto com AggregateFunction
- O método add () adiciona um elemento para acionar o cálculo AggregateFunction
- get () Pega o valor de State
Dois, descritor AggregatingState
Ao definir o descritor, o segundo parâmetro requer a classe AggregateFunction
//定义描述器
AggregatingStateDescriptor aggregatingStateDescriptor = new AggregatingStateDescriptor(
"avg-temp",
new SensorRecordUtils.MyAvgTemp(),
TypeInformation.of(new TypeHint<Tuple2<Double, Integer>>(){
})
);
//获取ReducingState
aggregatingState = getRuntimeContext().getAggregatingState(aggregatingStateDescriptor);
Terceiro, a classe AggregateFunction personalizada
Flink calcula o valor médio.O primeiro parâmetro da Tupla2 é a soma da temperatura atual e o segundo parâmetro é o número de dados.
Accumulator.f0 / Accumulator.f1 em getResult obtém o valor médio.
public static class MyAvgTemp implements AggregateFunction<SensorRecord, Tuple2<Double, Integer>, Double> {
@Override
public Tuple2<Double, Integer> createAccumulator() {
return Tuple2.of(0.0, 0);
}
@Override
public Tuple2<Double, Integer> add(SensorRecord value, Tuple2<Double, Integer> accumulator) {
Integer currentCount = accumulator.f1;
currentCount += 1;
accumulator.f1 = currentCount;
return new Tuple2<>(accumulator.f0 + value.getRecord(), accumulator.f1);
}
@Override
public Double getResult(Tuple2<Double, Integer> accumulator) {
return accumulator.f0 / accumulator.f1;
}
@Override
public Tuple2<Double, Integer> merge(Tuple2<Double, Integer> a, Tuple2<Double, Integer> b) {
return new Tuple2<>(a.f0 + b.f0, a.f1 + b.f1);
}
}
Quarto, o corpo principal do programa
public class Test06_AggregatingState {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//方便测试,设置为1
env.setParallelism(1);
DataStreamSource<String> source = env.socketTextStream(BaseConstant.URL, BaseConstant.PORT);
/*
设置watermark和指定时间属性
*/
SingleOutputStreamOperator<SensorRecord> dataStream = source
.map(new SensorRecordUtils.BeanMap());
dataStream
.keyBy(SensorRecord::getId)
.process(new MyKeyedProcessFunction())
.print();
env.execute();
}
}
Cinco, classe de processamento KeyedProcessFunction
public static class MyKeyedProcessFunction extends KeyedProcessFunction<String, SensorRecord, Tuple2<String, Double>> {
private transient AggregatingState aggregatingState;
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
//定义描述器
AggregatingStateDescriptor aggregatingStateDescriptor = new AggregatingStateDescriptor(
"avg-temp",
new SensorRecordUtils.MyAvgTemp(),
TypeInformation.of(new TypeHint<Tuple2<Double, Integer>>(){
})
);
//获取ReducingState
aggregatingState = getRuntimeContext().getAggregatingState(aggregatingStateDescriptor);
}
@Override
public void processElement(SensorRecord value, Context ctx, Collector<Tuple2<String, Double>> out) throws Exception {
aggregatingState.add(value);
out.collect(Tuple2.of(value.getId(), (Double) aggregatingState.get()) );
}
}