关于flink:单日课程超10万节VIPKID-如何通过实时计算提升上课体验

3次阅读

共计 6257 个字符,预计需要花费 16 分钟才能阅读完成。

VIPKID 介绍

VIPKID 是一家在线青少儿英语教育平台,成立七年以来,公司保持以赋能教育,启迪将来为使命,专一于一对一的线上教学模式,采纳 100% 的纯北美外教,学员遍布 63 个国家和地区。

截止目前,仅付费学生规模超 70 万人,单日一对一课量超 10 万节,顶峰时段课程并发最高达到 3.5 万节。领有笼罩了寰球 35 个国家的 5 条跨海专线,在 16 个国家、55 个城市实现数据中心传输节点布局,可能依据实时动静在一分钟内实现智能切换[1]。

外围业务场景

次要场景介绍

在一对一(一个老师和一个学生)模式的上课过程中,老师通过直播的模式以课件为辅助进行授课,互动的模式不仅包含直观的声音和视频还有聊天室以及在课件上写字划线拖动动作等,整个课程中波及多个组件模块。

各模块以协同依赖的形式提供服务,其中任意环节产生的事件对老师和学生都要做到可见和同步,如老师可看见学生在教室能力开始上课、学生可听见老师谈话、学生可看到老师翻页课件等能力持续失常上课直到完结。

在大规模网络教学中,流媒体实时互动 直播和 音讯实时数据传输 重大依赖用户设施和网络,数据体量大,尤其咱们是跨海传输的状况下变得十分辣手,对于网络稳定性有着十分刻薄的要求。

与大班网课直播相比,1v1 更重视互动,所以对问题的容忍度极低,任何一方的问题都会影响上课体验。其中场景之一为当呈现网络等异样问题时,用户就会点击”Help“按钮进行求助,此时须要监课人员(以下简称“FM”,来自 Fireman 缩写)立即染指解决,这对服务人员的规模和操作实时性有较大的需要。

以后业务痛点

目前在只有人工解决用户 Help 的模式下,因为日均 Help 申请量大(约占总课程的 10%),人均监课量大,同时从接管到申请到监课人员染指解决问题也须要辗转多个流程,会有以下问题:

  1. 问题解决不及时,用户容易期待,阻断上课,带给用户体验差;
  2. 人工解决效率低,课量减少以及大规模突发状况下,导致 FM 团队规模减少,须要更多人力;
  3. 有些用户出了问题,没有分割监课人员的话,问题被暗藏;

技术实现

为了解决上文提到的业务痛点问题,通过各环节业务特征提取及梳理,咱们设计了一种通过实时计算来产出业务标签,并利用标签数据进行主动监课来解决用户 Help 的计划。下文将重点形容整个计划的技术实现细节:波及到数据体系建设、自动化业务零碎建设、外围问题与优化以及最终收益成果:

  1. 数据体系建设:介绍用于撑持整个实时计算的 Vlink 数据平台、以后场景下相干业务数据采集和业务标签数据计算,是业务实现的撑持;
  2. 自动化业务零碎:介绍如何利用实时数据流来解决以后业务痛点;
  3. 问题与优化:介绍实现过程中碰到的业务和技术问题以及解决方案;
  4. 收益成果:介绍最终取得的收益成绩;

数据体系建设

整个数据体系建设的初衷是解决数据从哪里来、数据的业务逻辑是什么、如何计算、如何对立治理以及赋能更多场景,解决更多业务问题。

  1. Vlink 数据平台:介绍一站式数据平台,提供数据接入明细:

    a. 数据起源;

    b. 数据的业务含意;

    c. 数据打点法则,进步开发接入效率,解决上下游不明确问题;

  2. 业务数据采集:介绍以后场景下的业务数据采集;
  3. 业务数据计算:介绍如何利用 Flink 来计算简单逻辑的业务数据;

■ Vlink 数据平台

Vlink 数据平台是基于在 Flink Streaming Job 开发过程中一些问题的反思后,借鉴服务端开发上线流程,以研发人员为核心的进步开发效率,升高保护老本为出发点而设计研发的零碎,并反对 数据采集治理 打点接入治理 打点测试集成 等性能。

  • 次要性能点

1. 交互式运行作业

除 Flink Sql 外,业内对于 Streaming 类型的作业提交运行形式还是和官网提供的上传 Jar 包一样,打包 -> 期待并关注 -> 上传 -> 期待并关注 -> 运行。咱们联结运维团队,提供一键打包部署性能,可设置 AutoRun 在部署胜利后主动运行。

2. 批量执行操作:

在局部场景下须要局部或全量作业重启,当作业量很大时,是个费时费力的过程,而且比拟容易出错,那批量构建、进行与运行就变得很轻松,如:

  1. 某一类作业逻辑更新;
  2. 三方依赖库的降级更新;
  3. 集群降级;

3.SP 性能:交互式创立运行 SavePoint。

4. 血缘关系图:体现数据从打点到最终产出这一链路的上下游关系。

从图中能够分明地晓得处理程序 P1、P2 和 P3 的输入输出。

5. 其余性能: 

  1. 版本控制;
  2. 反对交互式开发 Flink SQL Job(仅反对 Kafka)。
  3. 数据 Schema 查问
  • 开发束缚

Flink 作业开发过程中,咱们发现外围逻辑是在 pipeline 过程中的 Function,同时有大量反复的逻辑 Function,比方,作业上下文配置、增加 Source 以及设置 WaterMark 等,所以咱们抽出了各层的逻辑封装成组件,并做了一些开发束缚,让开发者只关注外围逻辑。

1. 提供 ‘AbstractJobModel’,对立 Schema 化输出数据:

private[garlic] trait AbstractJobModel extends Serializable {
  def tm: Long // event time 事件工夫
  def ingestion: Long // ingestion time 摄入到到 Flink 零碎工夫
  def f: Boolean // for filter data that is useless 不符合条件要被过滤的数据
  def unNatural: Boolean // filter future data“超自然”数据
}

unNatural:因各端系统工夫不对立而造成的工夫戳大于当下工夫的数据,咱们称其为“超自然”数据,在工夫解决语义 EventTime 时须要特地关注。

2. 提供对立的灵便的 Kafka Source 初始化形式


/**
 *  指定生产工夫戳初始化办法
 */
def initSourceWithTm[T](deserializer: AbstractDeserializationSchema[T], topics: Array[String], tm: Long): SourceFunction[T]

/**
 *  指定生产工夫戳和 Kafka Server 初始化办法
 */
def initSourceWithServerAndTm[T](deserializer: AbstractDeserializationSchema[T], topics: Array[String], servers: String, tm: Long): SourceFunction[T]

/**
 *  通用初始化办法
 */
def initSource[T](implicit deserializer: AbstractDeserializationSchema[T], topics: Array[String], servers: String, tm: Long = 0L): SourceFunction[T]

3. 多模式 Sink Function

  1. sinkFilteredDataToKafka:不合乎规定或异样被过滤。
  2. sinkUnnaturalDataToKafka:超自然数据。
  3. sinkLateDataToKafka:乱序数据应提早而被 Window Function 抛弃。
  4. sinkDataInAndProcessToKafka:每条数据的摄入工夫和解决工夫。

4. 反对罕用的三方连贯组件

  1. Kafka
  2. Hbase
  3. ES
  4. JDBC

■ 业务数据采集

数据采集是整个数据处理架构的根底且重要环节,数据采集的实时性和准确性将间接影响到下层业务,采集形式有间接上传文件的形式和间接 Http 打点的形式。

事件数据埋点波及到挪动端、PC 端和服务端,以进教室为要害事件点:

  1. 用户发动进教室流程:加载 SDK 后,申请服务和网关,而后初始化服务组件流媒体、音讯通道和动静课件,当所有组件都没有异样时才示意进教室胜利了,否则持续重试逻辑直到进教室失败或胜利;
  2. 进教室胜利后,课程在失常进行中时,服务组件继续提供服务并实时上报数据。

整体而言埋点上有问题标签也有失常标签,依照进教室事件和组件类型,由粗到细可分一级、二级和三级。

  1. 进教室标签,用户有 0 到屡次进教室记录,因某一组件初始化失败而进不了教室和进教室过长,以及进教室胜利。
  2. 流媒体标签,次要有音视频卡顿、听不见彼此和看不见彼此以及音视频失常数据,数据打点百毫秒级别。
  3. 动静课件标签,次要有课件加载失败、课件动作不同步和无奈划线拖动。

■ 业务数据计算

本次业务计算对实时性要求极高,在技术选型上以 Flink 为主[2],天级别的离线数据分析会以 Spark 为主。

标签计算是整个自动化解决的关键点,指标计算的速度代表着零碎能解决的速度,数据来自多个业务流,联合以后的业务场景下,比拟典型的计算场景有:

a. 基于事件工夫的多流 union

 env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

    val stream = env.addSource(singleSource).name("signal")
       .union(env.addSource(avSource).name("av"))
      .union(env.addSource(dbySource).name("dby"))
      .union(env.addSource(enterSource).name("enter"))

      .filter(_.f)
      .filter(_.unNature)
      .assignTimestampsAndWatermarks(new DummyEventTimePunctuWaterMarks[InlineInputEventForm](6 * 1000))
      .filter(m => ***).name("***")

    val ***Streaam = stream
      .filter(f => ***)
      .keyBy(key => ***)
      .window(TumblingEventTimeWindows.of(Time.milliseconds(30 * 1000L)))
      .sideOutputLateData(***lateOutputTag)
      .apply(***WindowFunction)

    sink***ToKafka(***Streaam, ***name, recordFilter60s, ***kafkaSink, recordTmKafkaSink)

注:* 示意业务脱敏解决(下同)

b. 多流 Join

    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

    *** 省略局部逻辑代码 ***

    val ppt***JoinStream = ***Stream
      .coGroup(***Stream)
      .where(lb => ***)
      .equalTo(lb => ***)
      .window(SlidingEventTimeWindows.of(Time.milliseconds(30000), Time.milliseconds(15000)))
      //.sideOutputLateData(***LateOutputTag)
      .apply(ppt***CoGroupWindowFunction)

    sink***StreamToKafka(ppt***JoinStream, ***name, recordFilter60s, ***kafkaSink, recordTmKafkaSink)

coGroup 算子在目前的版本(1.7.2 及以上)不反对早退数据输入,曾经向社区提了相干 Jira[3]。

c. 异步加载维度数据

env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

  AsyncDataStream.unorderedWait(
      stream,
      syncGet***Function(),
      500L,
      TimeUnit.MICROSECONDS
    )

另外,维度数据计算时,依据实效性通过 GuavaCacheBuilder[4] 进行热数据缓存。

自动化业务零碎

咱们通过梳理上课中各关键环节点遇到的问题,从业务上,提出在用户发动 Help 后,且 FM 染指前做一层实时自动化服务的业务解决方案。

从技术上,该自动化业务零碎构建在整个 数据体系 之上,以上课过程中 实时标签数据 为根底,而后由标签零碎利用标签数据流通过 预检、自检 等伎俩自动化或半自动化来解决问题。对于零碎不能解决的问题,则转人工解决。

首先,课程中的问题有两种上报形式:

  1. 被动等用户发动 Help;
  2. 被动探测问题标签流;

而后验证逻辑模块过滤掉有效问题,如有效 Help、反复 Help、申请过期、FM 曾经染指以及非凡问题等,还有对于标签体系无奈笼罩的问题(比方乐音),则间接转 FM 人工解决。

若申请通过了验证模块且零碎可主动解决,则自检解决零碎可尝试进行切线,而后进行切线验证并将切线标记放入待处理队列 Pending,Pending 验证阶段实时获取失常标签流以内反馈的形式检测是否恢复正常。

问题与优化

整个业务场景对实时性要求极高,同时还要保障准确性以及须要晓得每一条数据的前因后果。对于没有正确计算到的 Case 要给出具体计算明细,比方数据在哪一层耗时导致达到解决引擎工夫过长、什么环节解决耗时过多、因为乱序哪些数据被丢掉了、如何进步加载维度信息速度、如何奇妙进步零碎处理量同时应用的计算资源又少、如何解决“超自然”数据等(具体见“Vlink 数据平台”)。

  1. 数据品质参差不齐,指标不统一:整个数据埋点波及 3 个部门跨 11 个团队,没有统一口径。通过 Vlink 数据平台按业务层级对立治理数据指标、端版本控制和验证流程;
  2. 实时计算下获取维度信息造成对 DB 库压力:a、在业务容许的前提下,通过小窗口聚合数据,缩小查问次数;b、依据数据时效性减少缓存;
  3. 无课程数据时“造数据”导致数据量翻倍:在串行逻辑下,前置多窗口且窗口大小与外围逻辑窗口大小保持一致,指定与 TaskManager*2 的分片数,预处理获取课程维度信息“造数据”再 shuffle 给上游外围窗口逻辑解决。

收益成果

截止目前,整体课中用户申请量降落了近 3%,没有造成其余业务指标上涨,无效晋升监课人员工作效率,解决提早低,反对多并发处理量,无效晋升了课程体验。

  1. 近 60% 求助能自动化解决,同时监课人员缩小近 40%;
  2. 用户求助后能在 20 秒内处理完毕,处理速度比人工更快,解决成功率高;
  3. 用户满意度高,投诉率升高了 2/3;

总结

本次以晋升课程品质和用户上课体验为出发点,利用实时计算技术构建根底标签数据系统,在业务上获得了硕大的成绩,也失去了公司的高度认可,除此之外也有很多意外播种,如晋升了课中体验的同时也晋升了人工效率、基于本次业务构建的标签零碎同样也能够利用到其余业务上,如全链路故障引擎、结课类型核心等。

因为在线教育的两大技术特色为 流媒体实时互动直播 音讯实时数据传输,其自身就带有实时属性,在很多业务场景上如课程实时进行、人员实时跟进服务等实时计算有诸多的用武之地。

相干援用

[1] https://www.donews.com/news/d…
[2] https://blog.scottlogic.com/2…
[3] https://issues.apache.org/jir…
[4] https://github.com/google/gua…

作者简介

甄国有,VIPKID 在线教室技术研发核心高级数据工程师,负责在线教室实时计算体系的落地和场景化,专一于数据体系建设和架构。

正文完
 0