import org.apache.flink.api.common.state.ReducingState;
import org.apache.flink.api.common.state.ReducingStateDescriptor;
import org.apache.flink.api.common.typeutils.base.LongSerializer;
import org.apache.flink.api.common.typeutils.base.IntSerializer;
import org.apache.flink.streaming.api.windowing.triggers.Trigger;
import org.apache.flink.streaming.api.windowing.triggers.TriggerResult;
import org.apache.flink.streaming.api.windowing.windows.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* @Auther WeiJiQian
* @描述 CountAndTimeTrigger : 满足一定条数和时间触发
* * 条数的触发使用计数器计数
* * 时间的触发,使用 flink 的 timerServer,注册触发器触发
*/
public class CountAndTimeTrigger<W extends Window> extends Trigger<Object, W> {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// 触发的条数
private final long size;
// 触发的时长
private final long interval;
private static final long serialVersionUID = 1L;
// 条数计数器
private final ReducingStateDescriptor<Integer> countStateDesc =
new ReducingStateDescriptor<>("count", new ReduceSum(), IntSerializer.INSTANCE);
// 时间计数器,保存下一次触发的时间
private final ReducingStateDescriptor<Long> timeStateDesc =
new ReducingStateDescriptor<>("fire-interval", new ReduceMin(), LongSerializer.INSTANCE); public CountAndTimeTrigger(long size, long interval) {
this.size = size;
this.interval = interval;
} // 每条元素到来时.
@Override
public TriggerResult onElement(Object element, long timestamp, W window, TriggerContext ctx) throws Exception {
// 注册窗口结束的触发器, 不需要会自动触发
// ctx.registerProcessingTimeTimer(window.maxTimestamp());
// count
ReducingState<Integer> count = ctx.getPartitionedState(countStateDesc);
//interval
ReducingState<Long> fireTimestamp = ctx.getPartitionedState(timeStateDesc);
// 每条数据 counter + 1
count.add(1);
if (count.get() >= size) {
System.out.println("窗口结束: 计数器触发 count : {}"+ count.get());
// 满足条数的触发条件,先清 0 条数计数器
count.clear();
// 满足条数时也需要清除时间的触发器,如果不是创建结束的触发器
if (fireTimestamp.get() != window.maxTimestamp()) {
// logger.info("delete trigger : {}, {}", sdf.format(fireTimestamp.get()), fireTimestamp.get());
ctx.deleteProcessingTimeTimer(fireTimestamp.get());
}
fireTimestamp.clear();
// fire 触发计算
return TriggerResult.FIRE;
} // 触发之后,下一条数据进来才设置时间计数器注册下一次触发的时间 timestamp = ctx.getCurrentProcessingTime();
// timestamp = System.currentTimeMillis();
if (fireTimestamp.get() == null) {
// long start = timestamp - (timestamp % interval);
long nextFireTimestamp = timestamp + interval;
// logger.info("register trigger : {}, {}", sdf.format(nextFireTimestamp), nextFireTimestamp);
ctx.registerProcessingTimeTimer(nextFireTimestamp);
fireTimestamp.add(nextFireTimestamp);
}
return TriggerResult.CONTINUE;
} // 处理时间到的时候,开始处理
@Override
public TriggerResult onProcessingTime(long time, W window, TriggerContext ctx) throws Exception { // count
ReducingState<Integer> count = ctx.getPartitionedState(countStateDesc);
//interval
ReducingState<Long> fireTimestamp = ctx.getPartitionedState(timeStateDesc); // time trigger and window end
if (fireTimestamp.get() != null && time == window.maxTimestamp()) {
System.out.println("窗口结束: 正常结束 {}" + time);
// 窗口结束,清0条数和时间的计数器
count.clear();
ctx.deleteProcessingTimeTimer(fireTimestamp.get());
fireTimestamp.clear();
return TriggerResult.FIRE_AND_PURGE;
} else if (fireTimestamp.get() != null && fireTimestamp.get().equals(time)) {
System.out.println("窗口结束:时间计数器触发, time : {}" + time);
// 时间计数器触发,清0条数和时间计数器
count.clear();
fireTimestamp.clear();
return TriggerResult.FIRE;
}
return TriggerResult.CONTINUE;
} @Override
public TriggerResult onEventTime(long time, W window, TriggerContext ctx) throws Exception {
// count
ReducingState<Integer> count = ctx.getPartitionedState(countStateDesc);
//interval
ReducingState<Long> fireTimestamp = ctx.getPartitionedState(timeStateDesc); // time trigger and window end
if (time == window.maxTimestamp()) {
System.out.println("窗口结束 : {}"+ time);
// 窗口结束,清0条数和时间的计数器
count.clear();
ctx.deleteProcessingTimeTimer(fireTimestamp.get());
fireTimestamp.clear();
return TriggerResult.FIRE_AND_PURGE;
} else if (fireTimestamp.get() != null && fireTimestamp.get().equals(time)) {
System.out.println("时间计数器触发, time : {}"+ time);
// 时间计数器触发,清0条数和时间计数器
count.clear();
fireTimestamp.clear();
return TriggerResult.FIRE;
}
return TriggerResult.CONTINUE;
} @Override
public void clear(W window, TriggerContext ctx) throws Exception {
ctx.getPartitionedState(countStateDesc).clear();
ctx.getPartitionedState(timeStateDesc).clear();
} // 多个slot 中的 数据合并.
@Override
public void onMerge(W window, OnMergeContext ctx) throws Exception {
super.onMerge(window, ctx);
ctx.mergePartitionedState(timeStateDesc);
ctx.mergePartitionedState(countStateDesc);
}
}

Flink 自定义触发器的更多相关文章

  1. flink 自定义触发器 定时或达到数量触发

    flink 触发器 触发器确定窗口(由窗口分配程序形成)何时准备由窗口函数处理.每个WindowAssigner都带有一个默认触发器. 如果默认触发器不适合需求,我们就需要自定义触发器. 主要方法 触 ...

  2. zabbix自定义触发器

    zabbix中监控项仅负责收集数据,而通常收集数据的目的还包括在某指标对应的数据超出合理范围时给相关人员发送告警信息,"触发器"正式 用于为监控项所收集的数据定义阈值,每一个触发器 ...

  3. Flink自定义Sink

    Flink自定义Sink Flink 自定义Sink,把socket数据流数据转换成对象写入到mysql存储. #创建Student类 public class Student { private i ...

  4. Flink 自定义source和sink,获取kafka的key,输出指定key

    --------20190905更新------- 沙雕了,可以用  JSONKeyValueDeserializationSchema,接收ObjectNode的数据,如果有key,会放在Objec ...

  5. 4、flink自定义source、sink

    一.Source 代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 1.1.flink内置数据源 1.基于文件 env.readTextFile(" ...

  6. 【Linux】Zabbix自定义触发器语法

    Zabbix触发器的语法如下: {<server>:<key>.<function>(<parameter>)}<operator>< ...

  7. zabbix自定义触发器进行监控

    给某一主机创建触发器 触发器属性,其中centos是主机名,也就是你监控的那台主机的名字,可以点击bp2,查看该主机的hostname 检测该触发器 在该主机下可以看到刚创建的触发器 最后我们给该主机 ...

  8. Flink 实现指定时长或消息条数的触发器

    Flink 中窗口是很重要的一个功能,而窗口又经常配合触发器一起使用. Flink 自带的触发器大概有: CountTrigger: 指定条数触发 ContinuousEventTimeTrigger ...

  9. Flink去重统计-基于自定义布隆过滤器

    一.背景说明 在Flink中对流数据进行去重计算是常有操作,如流量域对独立访客之类的统计,去重思路一般有三个: 基于Hashset来实现去重 数据存在内存,容量小,服务重启会丢失. 使用状态编程Val ...

随机推荐

  1. [COCI2016-2017#1] Mag

    [COCI2016-2017#1] Mag 题解 题目TP门 题目描述 你将获得一棵由无向边连接的树.树上每个节点都有一个魔力值. 我们定义,一条路径的魔力值为路径上所有节点魔力值的乘积除以路径上的节 ...

  2. MathType单边大括号的编辑技巧你知道吗?

    大家都知道,一般情况下,数学里面的括号都是成对出现的,但是也有些情况下可以只用到单边的括号,就比如分段函数,在编写的时候只需用到左半边的括号.MathType作为专业的公式编辑器,用它来编写公式再方便 ...

  3. 免费撸12个月AWS服务器

    前言 AWS联合博客园免费发送福利了,活动时间11月1号-11月31号,注册AWS免费体验12个月的服务器哦. 参考教程 官网教程: https://www.cnblogs.com/cmt/p/139 ...

  4. win10安装jenkins忘记密码的解决方法

    jenkins安装完了一直没用,突然想学习的时候,忘记了登陆密码. 一:修改配置文件 1. 打开jenkins的安装目录,选择users下面的admin目录下的config.xml文件   我的文件路 ...

  5. 【电子取证:FTK Imager篇】FTK Imager制作镜像详细介绍

    FTK Imager制作镜像详细介绍 以DD镜像制造为例,详细介绍了FTK Imager创建镜像的过程,记得大学的时候学习这些没什么教程,找到的资料也是语焉不详,故在此啰嗦一番---[suy] 一.磁 ...

  6. Session 与 sql 会话,mysql 权限设置,mybatis 逆向工程

    Session 与 Sql 会话注意点: 通过 sqlSessionFactoty 工厂建立的与sql的会话,在进行相应的插入操作后,需要进行 commit 操作才会让数据库执行插入更新操作.如何主键 ...

  7. 【初等数论】裴蜀定理&扩展欧几里得算法

    裴蜀定理: 对于\(a,b\in N^*, x, y\in Z\),方程\(ax+by=k\)当且仅当\(gcd(a, b)|k\)时有解. 证明: 必要性显然. 充分性:只需证明当\(k=gcd(a ...

  8. LeetCode双周赛#33 题解

    5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...

  9. @Transactional自调用问题

  10. 15_Android文件读写操作

    1. 文件的基本操作 File类的相关技巧和操作:文件的创建.重命名和删除,文件夹的创建和删除等操作. 1 package control; 2 3 import java.io.File; 4 5 ...