Spark应用卡住监控

前言

本文基于structured streaming开展。spark应用部署后因集群资源不足等问题导致应用出现‘卡住’现象,如下图所示。我们在应用部署后不可能时时关注应用的运行状况,应用可能卡住一晚、一天甚至更长时间,那么及时发现应用‘卡住’现象,排查卡住原因,也是很有必要的。

 

参考

1.spark官网提供了Monitoring Streaming Queries板块。有两种用于监视和调试active query的方式:interactively 和asynchronously,并给出了代码实现。我这里主要以asynchronously实现监控。


2.Spark2.2(三十九):如何根据appName监控spark任务,当任务不存在则启动(任务存在当超过多久没有活动状态则kill,等待下次启动) 该文章中实现卡住监控也是围绕asynchronously实现的,将query的实时状态信息写入hdfs,通过脚本监控达到应用重启动。

 

思路

考虑到业务场景,因spark应用不止一个,且每个应用不止一个query,期待当发现应用卡住的时候,可以进行告警提示,从而场景复现,及时排查问题。我的实现:将query的实时状态信息写入hbase,写一个服务定时查看hbase,当当前时间与query的状态信息超过一个阈值(比如15min)即告警。

 

实现

hbase表设计:rowkey:应用名称;列簇:info;列:appId(其value为该应用运行后的appId),queryIds(其value为该应用所有的queryId组合),queryId(其value为该query的实时活动时间)

 说明:为什么hbase中会考虑存储queryId?因为结合structured streaming的checkpoint机制,自应用启动后,queryId会保持不变,即使应用因某种原因导致中断再次重新启动,该queryId也是不变的。参考说明:

监听代码

public class Main {
    public static void main(String[] args) throws StreamingQueryException {
        SparkSession sparkSession = SparkSession.builder()
                .appName("sparkTest")
                .config("spark.sql.warehouse.dir", "./spark-warehouse")
                .master("local[*]")
                .getOrCreate();
        sparkSession.sparkContext().setLogLevel("warn");
        //监听
        sparkSession.streams().addListener(new QueryListener(sparkSession));

        //流处理,比如:消费kafka数据打印在控制台
        ......
        
        query.awaitTermination();
        query2.awaitTermination();
    }
}
public class QueryListener extends StreamingQueryListener {
    private SparkSession sparkSession = null;
    private Table table = null;
    private StringBuffer queryIds = new StringBuffer();
    
    public QueryListener(SparkSession sparkSession){
        this.sparkSession = sparkSession;
    }
    
    @Override
    public void onQueryStarted(StreamingQueryListener.QueryStartedEvent queryStarted) {
        queryIds.append(queryStarted.id().toString()+"***");
    }
    @Override
    public void onQueryTerminated(StreamingQueryListener.QueryTerminatedEvent queryTerminated) {
        ......
    }
    @Override
    public void onQueryProgress(StreamingQueryListener.QueryProgressEvent queryProgress) {
        String appId = this.sparkSession.conf().get("spark.app.id");
        String appName = this.sparkSession.conf().get("spark.app.name");
        String queryId = queryProgress.progress().id().toString();
        long time = new Date().getTime();

        ......
        Put put = new Put(Bytes.toBytes(appName));
        put.addColumn("info".getBytes(), ("appId").getBytes(), appId.getBytes());
        put.addColumn("info".getBytes(), ("queryIds").getBytes(), queryIds.toString().getBytes());
        put.addColumn("info".getBytes(), queryId.getBytes(), String.valueOf(time).getBytes());
        table.put(put);
        ......
    }
}

按照上述实现,就可以实时将应用的query时间写入hbase,然后再写个定时服务,监听hbase的info:{queryId},可以获取指定应用某一query的时间,判断该时间距离当前时间的差值,若超过自己设定的阈值则告警。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值