[spark 之webUi的入门知识-1]
1、spark-shell与spark-submit的区别:
就spark提交程序来说,最终都是通过spark-submit命令来实现的,不同的是spark-shell在运行时,会先进行一些初始参数的设置,然后调用spark-submit来运行,并且spark-shell是交互式的。
(1)spark-submit方式
- 将jar上传到集群,然后到/bin目录下通过spark-submit的方式,执行spark任务,格式:
>spark-submit --master spark的地址 --class 全类名 jar包地址 参数
- 举个栗子:运行spark自带的测试程序,计算pi的值
>./spark-submit --master spark://node3:7077 --class org.apache.spark.examples.SparkPi /usr/local/spark-2.1.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.1.0.jar 500
(2)spark-shell方式
相当于REPL工具,命令行工具,本身也是一个Application。
- 本地模式:不需要连接到Spark集群,在本地直接运行,用于测试,启动命令:bin/spark-shell 后面不写任何参数,代表本地模式:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">[root@bigdata111 bin]# ./spark-shell
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel). 19/06/18 17:52:17 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 19/06/18 17:52:27 WARN ObjectStore: Version information not found in metastore. hive.metastore.schema.verification is not enabled so recording the schema version 1.2.0
19/06/18 17:52:27 WARN ObjectStore: Failed to get database default, returning NoSuchObjectException 19/06/18 17:52:29 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException
Spark context Web UI available at http://192.168.226.111:4040
Spark context available as 'sc' (master = local[*], app id = local-1560851538355).
Spark session available as 'spark'.
Welcome to
____ __ / / ___ _____/ /__
\ / _ / _ `/ / '/
// ./_,// //_\ version 2.1.0
/_/ Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181)
Type in expressions to have them evaluated.
Type :help for more information.
scala> [root@bigdata111 bin]# 集群模式</pre>
- 启动命令:bin/spark-shell --master spark://.....
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">[root@bigdata111 spark-2.1.0-bin-hadoop2.7]# ./bin/spark-shell --master spark://bigdata111:7077</pre>
启动之后:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">[root@bigdata111 spark-2.1.0-bin-hadoop2.7]# ./bin/spark-shell --master spark://bigdata111:7077
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel). 19/06/18 22:47:54 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 19/06/18 22:48:07 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException
Spark context Web UI available at http://192.168.226.111:4040
Spark context available as 'sc' (master = spark://bigdata111:7077, app id = app-20190618224755-0000).
Spark session available as 'spark'.
Welcome to
____ __ / / ___ _____/ /__
\ / _ / _ `/ / '/
// ./_,// //_\ version 2.1.0
/_/ Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181)
Type in expressions to have them evaluated.
Type :help for more information.</pre>
2、
(1)上传一个小文件到hdfs上。
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">hdfs dfs -mkdir -p /spark/data
hdfs dfs -put /root/test/words /spark/data</pre>
(2)启动spark的standalone集群。进入到 $SPARK_HOME/sbin下,执行:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">./start-all.sh</pre>
可以在浏览器验证8080端口,即是否集群启动成功。
image(3)运行spark-shell
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">./spark-shell --master spark://node1:7077</pre>
启动日志的说明:
image这里可以直接用SparkContext=>sc,SparkSession=>spark
还有需要注意的是,我们的spark-shell执行后,在Ui(8080界面)就会有Running Application(下下图所示)
(4)在hdfs上读取数据(注意自己的50070界面配置的hdfs的通信端口是900还是8020)
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">sc.textFile("hdfs://node1:9000/spark/data/words")</pre>
此时worker变为2个:
image(5)先看worker(右键上述worker Id在新窗口打开)
image即不同角色的端口号是不同的,8080是Master的,8081是Worker的。
(6)看具体的name(右键spark shell 在新窗口打开)
image image(7)此时spark-shell下执行wordCount代码(回车):
image运行完之后,回到Ui界面:
image以及这里可以看到driver以及2个executor以及action算子在哪个时间点启动的:
image下面探讨一下为啥是4个task:点击jobs(点击jobs查看具体的stages),右键在新窗口打开:
image打开新的窗口:
image我们的0号stage对应着wordcount程序中reduceByKey前边的代码,且通过上图看出0号stage有2个task。task的个数(stage的并行度)是由rdd的分区数决定的,而rdd的分区是由读取文件的block数决定的,因为上传到hdfs的是小文件(不到2kb),通过50070端口界面查看到只有1个block。那么为什么task变成了2?我们来查看一下源码中的textFile。
image官网:
image image上述源码点进去:这里最终去了个min,所以最后的结果是2:
image虽然这里最终是2。我们也可以提高分区(并行度),比如使用一些算子。
(8)继续看web Ui:
image(9)界面顺序:jobs => stages => tasks
image这里进入了tasks:
image(10)event timeline(根据这个图可以看执行的job是否有数据倾斜)
image假设当前的stages中有1000个task,上述图有1000个柱状条,如果绝大多数绿色柱状条都在某个时间点(较靠前)停止,但是某个task的绿色柱状条要长好多, 则很有可能发生了数据倾斜。
我们还可以点击[DAG visualization]查看有向无环图,查看算子之间的依赖。
还有就是[Aggregated Metrics by Executor]查看以executor为纬度的统计。
[Summary Metrics for ...]查看更细节的信息对于tasks。上面选择[select all]还可以展示更多所有的信息。
image上述划分阶段(min-25%-median-75%-max)的作用是可以随机取一个task查看其在整个的task中执行水平(比如 执行的快还是慢)。
(11)storage(存储)
我们代码中的presits和cache持久化的数据都是在这里进行显示的。下面模拟(注意cache是懒执行的,需要最后加一个action算子):
image刷新storage的界面:
image如果此时在终端卸载cache并再次刷新此界面:
image image(11)environment
image显示:依赖的jar包、jdk的版本、spark安装位置等。
image(12)executors
image(13)退出spark-shell
image image因为现在已经停止了application,所以之前的(上述内容---jobs、stages、tasks等)无法访问了。需配置历史服务(下一个blog)。