El caso de uso AggregatingState de la gestión del estado de Keyed State para encontrar el valor promedio
Serie de articulos
Tutorial de Flink (13) Gestión de estado de estado con clave ValueState usando alarma de diferencia de temperatura
Tutorial de Flink (14) Gestión de estado de estado con clave Caso de uso de MapState
Tutorial de Flink (15) Gestión de estado de estado con clave ListState usando ValueState para implementar
tutorial de Flink (16) Estado de estado con clave The ReducingState caso de uso de administración para encontrar el valor máximo
Tutorial de Flink (17) El caso de uso de AggregatingState de administración de estado de Keyed State para encontrar el valor promedio
Uno, el método de AggregatingState
- AggregatingState debe usarse junto con AggregateFunction
- El método add () agrega un elemento para activar el cálculo AggregateFunction
- get () Obtiene el valor de State
Dos, descriptor AggregatingState
Al definir el descriptor, el segundo parámetro requiere la clase AggregateFunction
//定义描述器
AggregatingStateDescriptor aggregatingStateDescriptor = new AggregatingStateDescriptor(
"avg-temp",
new SensorRecordUtils.MyAvgTemp(),
TypeInformation.of(new TypeHint<Tuple2<Double, Integer>>(){
})
);
//获取ReducingState
aggregatingState = getRuntimeContext().getAggregatingState(aggregatingStateDescriptor);
En tercer lugar, la clase personalizada AggregateFunction
Flink calcula el valor promedio El primer parámetro de Tuple2 es la suma de la temperatura actual y el segundo parámetro es el número de datos.
Acumulador.f0 / acumulador.f1 en getResult obtiene el valor promedio.
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);
}
}
Cuarto, el cuerpo principal del 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, clase de procesamiento 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()) );
}
}