Spark on k8s: OkHttp WebSocket 非daemon线程导致Driver线程无法退出

问题描述

基于Spark 3.0-SNAPSHOT(unreleased),做Spark-Terasort相关测试,任务正常的话分如下图所示两个stage,

spark terasort job

第一个,stage 0,读取hdfs input目录数据,并进行shuffle write
第二个,stage 1,进行shuffle read,并向hdfs output目录的输出

其中一次测试由于hdfs存储的配额不足,导致stage 1失败,fail 整个spark job,如下图所示。

spark terasort job error

此时按照Spark on k8s正常的逻辑,会执行到SparkContext.stop, 各类线程该停停该关关,各executor进程应该收到exit的命令,然后做完这些,主线程退出,留给JVM收尾最后Driver 进程停止。当然Driver pod会留给k8s去进行垃圾回收。

然而在实际的情况下,却发现整个Spark作业依然占着k8s集群的资源,Driver pod状态一直处于running的状态。


image.png

在client侧自然也无法获得该作业的“实际状态”


image.png

在这种情况下,Spark on k8s作业就无法像类似Spark on yarn的作业,不依靠一些额外的监控手段才能感知app的运行状态。

测试的过程中,模拟了各种失败的场景,stage/job级别的异常基本上,都让app卡死了.

原因分析

分析Spark on k8s作业的异常,和其他调度器(yarn等)作业也基本一致,各进程的日志信息,jstack信息,gc信息等,还可以通过Spark UI 获取一些作业相关的信息。区别点在于Spark on k8s可能还需要看下各个Pod的状态等相关信息

  1. 首先查看Driver Pod状态,未见异常


    driver pod status
  2. 查看Driver/executor进程jstack


    driver jstack
executor jstack

果不其然,driver 进程中 DestoryJavaJVM被一个OkHttp WebSocket...非daemon线程给拦住了去路...

根据线程的名字可以猜到这个driver端启动的k8s api server 通信的client有关

翻翻Spark 源码

  1. Driver侧的 k8s client有定义关闭自己的逻辑
  2. Spark 在初始化OkHttpClient的时候把ping interval设置为0,
val config = new ConfigBuilder(autoConfigure(kubeContext.getOrElse(null)))
      .withApiVersion("v1")
      .withMasterUrl(master)
      .withWebsocketPingInterval(0)
      .withRequestTimeout(clientType.requestTimeout(sparkConf))
      .withConnectionTimeout(clientType.connectionTimeout(sparkConf))
      .withOption(oauthTokenValue) {
        (token, configBuilder) => configBuilder.withOauthToken(token)
      }.withOption(oauthTokenFile) {
        (file, configBuilder) =>
            configBuilder.withOauthToken(Files.toString(file, Charsets.UTF_8))
      }.withOption(caCertFile) {
        (file, configBuilder) => configBuilder.withCaCertFile(file)
      }.withOption(clientKeyFile) {
        (file, configBuilder) => configBuilder.withClientKeyFile(file)
      }.withOption(clientCertFile) {
        (file, configBuilder) => configBuilder.withClientCertFile(file)
      }.withOption(namespace) {
        (ns, configBuilder) => configBuilder.withNamespace(ns)
      }.build()

而OkHttpClient 中 pingIntervalMillis 为0时,这个线程并不会被调度。。

public void initReaderAndWriter(
      String name, long pingIntervalMillis, Streams streams) throws IOException {
    synchronized (this) {
      this.streams = streams;
      this.writer = new WebSocketWriter(streams.client, streams.sink, random);
      this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false));
      if (pingIntervalMillis != 0) {
        executor.scheduleAtFixedRate(
            new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS);
      }
      if (!messageAndCloseQueue.isEmpty()) {
        runWriter(); // Send messages that were enqueued before we were connected.
      }
    }

    reader = new WebSocketReader(streams.client, streams.source, this);
  }

开始凌乱了。。。

既然定义了自己关闭的逻辑,没有正常的关闭,想必是有没法捕获的系统异常发生,比如OOM

但是第2点就没法解释了,jar包冲突,不兼容?尝试把okhttp的构件升级到kubernetes-client的依赖版本(3.12.0)依然没有用。。

解决办法

https://issues.apache.org/jira/browse/SPARK-27927
https://issues.apache.org/jira/browse/SPARK-27812
目前社区对这个问题有两个类似的issue跟踪,其中也不乏一些尝试,不乏一些原因的猜测,但貌似都没找到根源。

可以尝试的方法,

  1. 回退kubernete-client到3.0版本
  2. 加上 -XX:OnOutOfMemoryError="kill -9 %p"来跑,可以规避一些driver oom导致的问题
  3. 使用UncaughtExceptionHandler
  4. 调用System.exit
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 耗子,第二天了,我很想你 我会给你足够的时间考虑我们之间的关系,我会在明后天去找你试着挽回你,但我不希望你单单因为...
    DniWeR阅读 187评论 0 0
  • 爱不是配不配,也不是绑架,是一种突如其来的感觉,自从遇见你,认识你,你就是我生命中的阳光,每天简短的一句问候,适合...
    liandjun阅读 228评论 0 0
  • 我独自漂泊来到了这里 繁华的都是把我淹没 我一个人在着漆黑的夜里 望着天空默默地哭泣 我不知道夜空为何会那么漆黑 ...
    车菊子阅读 531评论 0 1
  • 开营及野人大叔A1 A2讲解,很具体,而且娓娓道来,有节奏,力求每一步都让学员听懂,讲解完还有小测试,这是个苹果。...
    陈念媛阅读 176评论 0 0