spark 2.4.0源码分析--(二)AppStatusListener与SQLAppStatusListener事件响应及存储

接上一篇文章,LiveListenerBus事件总线分发的event,一个非常重要的目标就是存入AppStatusListener,SQLAppStatusListener内部的kvstore: ElementTrackingStore,用于Spark UI展示 :

  • Spark UI中Job、Stage、Task页面,调用AppStatusStore提供的方法,读取kvstore中存储的rdd任务相关信息。
  • Spark UI中SQL页面,调用SQLAppStatusStore提供的方法,读取kvstore中存储的SparkPlan物理计划(SQL真实执行流程)相关信息。

一、KVStore定义及实现

在这里插入图片描述
KVStore是一个特质,定义了数据的读、写、删除、count()计算总数等方法,其两个重要的实现是InMemoryStore和ElementTrackingStore

1、InMemoryStore内存方式存储

  • InMemoryStore内部定义了数据结构:
    ConcurrentMap<Class<?>, InstanceList> data = new ConcurrentHashMap<>()
  • 上述data是围绕记录的class类型进行分类存储。
    InstanceList内部保存了某个对应class数据的多条信息,例如UI默认展示的1000个Stage信息,其调用顺序AppStatusStore.stageList(xxx) —> store.view(classOf[StageDataWrapper])
  • store.view(xxx)方法返回的是KVStoreView的子类InMemoryView(),可以对InstanceList内部的数据进行排序,也就是我们在UI中看到的最新Stage信息总在最前
  • 在调用InMemoryView iterator()方法时,会先将内部elements数据进行排序,并根据设置的first、last、skip信息对sorted数据进行过滤,最后返回一个InMemoryIterator
public class InMemoryStore implements KVStore {
	...
	private ConcurrentMap<Class<?>, InstanceList> data = new ConcurrentHashMap<>();

    // 统计某一class数据总量,例如store.count(classOf[SQLExecutionUIData])统计运行的SQL总量
	@Override
    public long count(Class<?> type) {
      InstanceList list = data.get(type);
      return list != null ? list.size() : 0;
    }

    // 某一对象的数据量,例如store.count(classOf[TaskDataWrapper], "stage", Array(stageId, stageAttemptId))获取某个stage的task总数
	@Override
  public long count(Class<?> type, String index, Object indexedValue) throws Exception {
    InstanceList list = data.get(type);
    int count = 0;
    Object comparable = asKey(indexedValue);
    KVTypeInfo.Accessor accessor = list.getIndexAccessor(index);
    for (Object o : view(type)) {
      if (Objects.equal(comparable, asKey(accessor.get(o)))) {
        count++;
      }
    }
    return count;
  }

 // 获取某一class指定key数据,例如:store.read(classOf[SQLExecutionUIData], executionId)获取指定executionId的SQL运行描述detail
  @Override
  public <T> T read(Class<T> klass, Object naturalKey) {
    InstanceList list = data.get(klass);
    Object value = list != null ? list.get(naturalKey) : null;
    if (value == null) {
      throw new NoSuchElementException();
    }
    return klass.cast(value);
  }

// 写入一条数据,先获取数据的class,不存在则先创建class对应的数据列表Ins
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值