Overview

  • 这一部分我们主要讨论如果配置一个Spark application,如何tune and debug Spark workloads
  • 配置对Spark应用性能调优很重要。我们有必要理解一个Spark应用的性能。

Configuring Spark with SparkConf

  • 我们知道,在创建SparkContext的时候会需要SparkConf实例。一个例子:
  • val conf = new SparkConf()
    .setAppName("Test")
    .setMaster("local")
    val sc = new SparkContext(conf)
  • SparkConf类很简单,包含一些用户可覆盖的配置选项的键值对
  • 也可以通过spark-submit动态地设置配置。基于这种方法,你可以在程序中new一个“空”的SparkConf,直接传给SparkContext。这种方式下可以直接使用 --conf标记,该标记之后可以使用任何Spark配置值。例子:
  • bin/spark-submit \
    --class com.wtttt.spark.test \
    --master local \
    --name "test" \
    --conf spark.ui.port=36000 \
    test.jar
  • 这种spark-submit的方式除了可以使用--conf,还可以从文件加载。缺省情况下,spark-submit会在conf/spark-defaults.conf中读取whitespace-delimited 的键值对。你也可以使用

    --properties-file 来指定conf文件。例子:

    bin/spark-submit \
    --class com.wttttt.spark.test \
    --properties-file my-config.conf \
    test.jar
    ## Contents of my-config.conf ##
    
    spark.master    local[4]
    spark.app.name "test"
    spark.ui.port 36000
  • 如果多处同时设置的话,程序设置的优先级高于spark-submit指定的。
  • 完整的conf选项参考 spark configuration

Components of Execution: Jobs, Tasks, and Stages

  • 我们知道,Spark会把逻辑表示翻译成一系列物理执行计划,by merging multiple operations into tasks.
  • 看下面的例子:
    val input = sc.textFile("input.txt")
    
    val tokenized = input.
    map(line => line.split(" ")).
    filter(words => words.size > 0) val counts = tokenized.
    map(words => (words(0), 1)).
    reduceByKey{ (a, b) => a + b} // example of the source file "input.txt"
    ## input.txt ##
    INFO This is a message with content
    INFO This is some other content
    (empty line)
    INFO Here are more messages
    WARN This is a warning
    (empty line)
    ERROR Something bad happened
    WARN More details on the bad thing
    INFO back to normal messages
  • 当我们在shell输入上述语句之后,并不会执行任何actions,只会隐式地定义一个DAG(有向无环图)。我们可以用toDebugString来看看:
  • scala> counts.toDebugString
    res84: String =
    (2) ShuffledRDD[296] at reduceByKey at <console>:17
    +-(2) MappedRDD[295] at map at <console>:17
    | FilteredRDD[294] at filter at <console>:15
    | MappedRDD[293] at map at <console>:15
    | input.text MappedRDD[292] at textFile at <console>:13 | input.text HadoopRDD[291] at textFile at <console>:13
  • 我们执行一个action来触发计算: counts.collect()
  • 这时,Spark的调度器scheduler会创建一个物理执行计划来计算该action所需的RDDs(递归地向前找所有需要的RDDs)。
  • 更复杂的情况是,stages的物理集合不是与RDD graph 1:1对应的。这种情况发生在scheduler执行pipelining或者合并多个RDDs到一个stage的时候。pipelining发生在RDDs可以从parents本地计算的时候(不需要data movement)。
  • 对于上面的例子,计算counts的时候,即使counts有很多个parent RDDs,它也只存在two levels of indentation。所以它的物理执行只需要两个stages。该例中的pipelining就是因为有多个filter和map的序列。如下图:
  • 运行这个action,看spark UI: 一共一个job,两个stages。
    • Completed Jobs (1)
    • Completed Stages (2)

  • 除了pipelining,Spark内部的scheduler也会在有RDD已经被persisted到内存或磁盘的时候缩短RDD graph的lineage。
  • 还有一种(可缩短lineage的)情况是,RDD已经通过之前的shuffle被materialized到磁盘。即使没有显式地调用persist()。这种情况是充分利用了shuffle的输出会写到磁盘的特点。
  • 做个实验:
    counts.cache()
    counts.collect()

    看下这个job的stages:

  

可以看到只执行了一个stage,另一个被skip了。

  • 以上,Spark执行的时候包括这么几个阶段:
    1. User code定义一个RDD的DAG;
    2. Actions force DAG到执行计划的translation;这时Spark调度器提交一个job来计算所有所需的RDDs。该job会有一或多个stages,它们是由task组成的并行计算浪潮(parallel waves of computation composed of tasks)。由于pipelining,每个stage可以对应多个RDDs。
    3. Tasks被调度,在集群上执行;stages按顺序执行,individual tasks执行RDD的各个部分。

Finding Information

  • 具体的进度信息、性能度量可以在Spark web UI以及driver和executor的logfiles中找到。

Spark Web UI

  • 说明:YARN cluster模式下,application driver是运行在cluster内部的,因此你需要通过YARN resourceManager来访问UI。

Jobs: Progress and metrics of stages, tasks, and more

  • 一般首先是点进去一个比较慢的stage,其内部可能存在skew,因此你可以看下是否某些tasks运行时间过长。比如你可以看是否这些tasks read, write or compute much more than others?
  • 你还可以看每个task读、计算、写分别占用的时间。如果tasks花很少时间读写,那么可能user code本身是expensive的,作为solution之一你可以参考advanced programming中提到的"Working on a Per-Partition Basis"来减少比如创建对象的开销。 但是如果tasks花费很多时间来从外部系统读取数据,那么可能不存在更多的外部优化方式。

Storage: Information for RDDs that are persisted

  • storage页面包含了persisted RDDs的信息。
  • 通常,如果很多RDDs都会缓存的话,older ones可能会被移除。

Executors: A list of executors present in the application

  • 该页列出了应用中活跃的executors,以及每个executor在处理和存储中的一些度量。
  • 这一页的用处是你可以确认你的application拥有你所预期的资源。

Environment: Debugging Spark's configuration

  • This page enumerates the set of active properties in the environment of your Spark application.

Driver and Executor logs

  • YARN模式下,最简单的收集日志的方式是使用YARN日志收集工具

    • (running yarn logs -applicationId <app ID>)

<Spark><Tuning and Debugging>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Confluence 6 创建一个空间

    在 Confluence 中并不限制你可以创建多少空间.你可以选择为你每一个小组,项目都创建一个空间,或者你也可以将这 2 者混合在一起.所有的这些都基于你的需求来决定的. 每一个 Confluenc ...

  2. DRF之简介以及序列化操作

    1. Web应用模式. 在开发Web应用中,有两种应用模式: 前后端不分离 2.前后端分离 2. api接口 为了在团队内部形成共识.防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实 ...

  3. 118. Pascal's Triangle (java)

    问题描述: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5 ...

  4. vue组件插槽

    vue中子组件内容如何定义为可扩展的呢,就是用slot插槽来实现.如下图 如果<slot></slot>标签有内容,那就默认显示里面的内容,父组件传了就会覆盖此默认的内容.

  5. .net 基础

    之前给大家总结了java的面试几次技巧总结,同学们看了觉得还是不错,能够得到大家的认可,感觉还是挺不错的.现在又有同学来想小编索要.NET面试的总结了,好吧.谁让小编这么好呢!以下是.NET面试之框架 ...

  6. centos命令行系列之centos6防火墙的关闭以及开启

    输入:cat /etc/issue   查看版本 (一)通过service命令 注:service命令开启以及关闭防火墙为即时生效,下次重启机器的时候会自动复原 查看防火墙状态:service ipt ...

  7. [转]一次CMS GC问题排查过程(理解原理+读懂GC日志)

    这个是之前处理过的一个线上问题,处理过程断断续续,经历了两周多的时间,中间各种尝试,总结如下.这篇文章分三部分: 1.问题的场景和处理过程:2.GC的一些理论东西:3.看懂GC的日志 先说一下问题吧 ...

  8. 微信小程序FAQ

    1. 图片名注意大小写. 不然本地预览是可以看到的.上传后用手机就看不到了. 2. bindtap等事件传参 wxml <view id="tapTest" data-hi= ...

  9. laravel查找某个类拥有的方法:

    1.在当前项目下,使用cmd窗口,输入: php artisan tinker 在输入: app('log') 显示出:Illuminate\Log\Writer 2.在phpstorm中按:shif ...

  10. C++解析四-友员函数、内联函数、静态成员

    友元函数 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员.尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数.友元可以是一个函 ...