今天在调试代码,关于timeWindow的例子,发现把timeWindow的相关代码注释掉了,发送一个数据,也会延迟很久才会进行计算。 如下代码
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
DataStream<Tuple2<String, String>> map = env.socketTextStream("192.xxx.xxx.xxx", 9000)
.map(new MapFunction<String, Tuple2<String, String>>() {
@Override
public Tuple2<String, String> map(String s) throws Exception {
return new Tuple2<String, String>(s.split(",")[0], s.split(",")[1]);
}
});
map.keyBy(0)
.map(new MapFunction<Tuple2<String, String>, Object>() {
@Override
public Object map(Tuple2<String, String> value) throws Exception {
return value;
}
}).print();
env.execute("TestOrderMain");
以上代码没有用到window窗口,按理说是进来一条数据,应该马上就会执行一条数据,结果表现为:
- 第一段map算子逻辑拿上会执行
- 第二段keyby后的map算子逻辑代码会不定时延迟一会才会执行
然后一直一脸懵逼的发呆,突然在眼神游离之时就看到了这行代码
env.setBufferTimeout(60*1000);
翻译成中文是缓存超时时间,冥冥之中感觉自己找到了,然后就疯狂google相关文档,整理为知识点以备不时之需。
控制执行时间
默认的,element在网络传输时不是一个个单独传输的(这会导致不必要的网络流量),而是缓存后传输
缓存(是在设备间传输的实际单位)的大小可以在Flink的配置文件中设置
ps:目前在配置文件中只找到该关于缓存的配置,若有不对,请及时指出
# The amount of memory going to the network stack. These numbers usually need
# no tuning. Adjusting them may be necessary in case of an "Insufficient number
# of network buffers" error. The default min is 64MB, teh default max is 1GB.
#
# taskmanager.network.memory.fraction: 0.1
# taskmanager.network.memory.min: 64mb
# taskmanager.network.memory.max: 1gb
尽管该方法有益于优化吞吐量,他会在stream到达不够快时导致执行时间方面的问题。为了控制吞吐量和执行时间,你可以在执行环境(或独立的Operator)中调用env.setBufferTimeout(timeoutMillis)来设置等待装满buffer的最大等待时间,在这个时间过后,不管buffer是否已满,它都会自动发出。该默认超时时间是100ms。
下例是设置API的用法:
LocalStreamEnvironment env = StreamExecutionEnvironment.createLocalEnvironment();
env.setBufferTimeout(timeoutMillis);
env.genereateSequence(1,10).map(new MyMapper()).setBufferTimeout(timeoutMillis);
要最大化吞吐量,设置setBufferTimeout(-1)来去除超时时间,则buffer仅在它满后才会被flush。要最小化执行时间,设置timeout为一个接近0的数字(如5ms或10ms)。应当避免设置Timeout为0,因为它会造成严重的性能下降。
最后设置为5ms解决了该问题