Livy探究(一) -- 初體驗

Livy探究(一) -- 初體驗
Livy探究(二) -- 運行模式
Livy探究(三) -- 核心架構細節探索
Livy探究(四) -- 從es讀取數據
Livy探究(五) -- 解釋器的實現
Livy探究(六) -- RPC的實現
Livy探究(七) -- 編程接口分析

Livy是Apache的開源項目,目前仍然處於孵化階段。它提供了一種經過restful接口執行交互式spark任務的機制。經過它能夠進一步開發交互式的應用。固然,交互式spark應用其實有許多實現。本系列與你們一塊兒對Livy作個探索java

簡介

提交spark任務通常有兩種方式:python

  • 經過spark shell編寫交互式的代碼
  • 經過spark submit提交編寫好的jar包到集羣上運行,執行批處理任務

Livy交互式批處理都搬到了web上,提供restful接口,下面是Livy的架構圖:web

Livy會爲用戶運行多個session,每一個session就是一個常駐的spark context。用戶經過restful接口在對應的spark context執行代碼。session能夠運行在local模式standalone集羣或者yarn集羣模式下。shell

藉助Livy或者其思想,咱們主要是但願能夠開發交互式數據平臺apache

安裝

選一臺Hadoop集羣中的機器,從Livy官網下載livy:編程

wget https://mirrors.tuna.tsinghua.edu.cn/apache/incubator/livy/0.7.0-incubating/apache-livy-0.7.0-incubating-bin.zip
Livy依賴spark,因此另外須要下載和解壓好spark

設置好spark環境,例如json

export SPARK_HOME=/home/spark-2.4.1-bin-hadoop2.7

設置好hadoop環境,例如segmentfault

export HADOOP_CONF_DIR=/etc/hadoop/conf

運行livy:api

bin/livy-server start

因爲個人hadoop開啓了kerberos認證,因此會報錯。經過報錯的提示,咱們須要配置一下kerberos:服務器

cp conf/livy.conf.template conf/livy.conf
vi conf/livy.conf
# 增長以下兩行
livy.server.launch.kerberos.principal=spark1@xxxxx.COM
livy.server.launch.kerberos.keytab=/var/keytab/spark1.keytab

Livy啓動後,默認監聽端口爲8998,經過web訪問這個端口:

image.png

提示尚未建立任何session,接下來咱們經過官網的example啓動一個交互式session

第一個session

在交互式python中,運行以下python代碼,提交一個session,並嘗試運行一個scala命令1 + 1(注意替換其中的host):

import json, pprint, requests, textwrap
host = 'http://vm3198:8998'
data = {'kind': 'spark'}
headers = {'Content-Type': 'application/json'}
r = requests.post(host + '/sessions', data=json.dumps(data), headers=headers)

# 此處會提交一個spark類型的session,稍等幾秒後繼續

statements_url = host + r.headers['location'] + '/statements'
data = {'code': '1 + 1'}
r = requests.post(statements_url, data=json.dumps(data), headers=headers)

# 此處會將1+1這個scala語句提交到服務端執行,執行是異步的,因此等幾秒鐘後,經過接口查看結果

statement_url = host + r.headers['location']
r = requests.get(statement_url, headers=headers)
pprint.pprint(r.json())

{'code': '1 + 1',
 'completed': 1601521233533,
 'id': 0,
 'output': {'data': {'text/plain': 'res0: Int = 2n'},
 'execution_count': 0,
 'status': 'ok'},
 'progress': 1.0,
 'started': 1601521233404,
 'state': 'available'}

經過web看下建立的session和執行的語句:

image.png

觀察服務器啓動的進程:

.../java -cp /home/spark-2.4.1-bin-hadoop2.7/conf/:/home/spark-2.4.1-bin-hadoop2.7/jars/*:/etc/hadoop/conf/ -Xmx1g org.apache.spark.deploy.SparkSubmit \
--properties-file /tmp/livyConf142660555568889215.properties \
--class org.apache.livy.rsc.driver.RSCDriverBootstrapper spark-internal

能夠看到,livy運行了一個SparkSubmit,driver類爲org.apache.livy.rsc.driver.RSCDriverBootstrapper,更重要的是看下生成的臨時配置文件,其中比較關鍵的配置以下:

...
spark.master=local
spark.jars=/home/apache-livy-0.7.0-incubating-bin/rsc-jars/netty-all-4.0.37.Final.jar,/home/apache-livy-0.7.0-incubating-bin/rsc-jars/livy-api-0.7.0-incubating.jar,/home/apache-livy-0.7.0-incubating-bin/rsc-jars/livy-rsc-0.7.0-incubating.jar,/home/apache-livy-0.7.0-incubating-bin/rsc-jars/livy-thriftserver-session-0.7.0-incubating.jar,/home/apache-livy-0.7.0-incubating-bin/repl_2.11-jars/livy-core_2.11-0.7.0-incubating.jar,/home/apache-livy-0.7.0-incubating-bin/repl_2.11-jars/commons-codec-1.9.jar,/home/apache-livy-0.7.0-incubating-bin/repl_2.11-jars/livy-repl_2.11-0.7.0-incubating.jar
spark.__livy__.livy.rsc.driver-class=org.apache.livy.repl.ReplDriver
...

能夠看到livy是使用local模式啓動的SparkContext。這些信息對於咱們後續分析源碼是很重要的,至關於執行的入口。

接下來再建立一個經典的PI任務。依然是經過python交互模式,運行以下代碼

# 再建立一個statement,用於執行PI任務
data = {
  'code': textwrap.dedent("""
    val NUM_SAMPLES = 100000;
    val count = sc.parallelize(1 to NUM_SAMPLES).map { i =>
      val x = Math.random();
      val y = Math.random();
      if (x*x + y*y < 1) 1 else 0
    }.reduce(_ + _);
    println("Pi is roughly " + 4.0 * count / NUM_SAMPLES)
    """)
}
r = requests.post(statements_url, data=json.dumps(data), headers=headers)
statement_url2 = host + r.headers['location']

# 稍等幾秒鐘,等待執行完成,檢查執行結果
r = requests.get(statement_url2, headers=headers)
pprint.pprint(r.json())
{'code': '\n'
         'val NUM_SAMPLES = 100000;\n'
         'val count = sc.parallelize(1 to NUM_SAMPLES).map { i =>\n'
         '  val x = Math.random();\n'
         '  val y = Math.random();\n'
         '  if (x*x + y*y < 1) 1 else 0\n'
         '}.reduce(_ + _);\n'
         'println("Pi is roughly " + 4.0 * count / NUM_SAMPLES)\n',
 'completed': 1601522536564,
 'id': 1,
 'output': {'data': {'text/plain': 'NUM_SAMPLES: Int = 100000\n'
                                   'count: Int = 78560\n'
                                   'Pi is roughly 3.1424\n'},
            'execution_count': 1,
            'status': 'ok'},
 'progress': 1.0,
 'started': 1601522534363,
 'state': 'available'}

再次看下web界面,增長了一個statements:

image.png

總結

經過第一個session的實驗,咱們能夠掌握如何經過livy的restful接口建立session,並在同一個session(同一個SparkContext)中執行多個交互式的代碼。而且livy默認啓動的是local模式的SparkContext。

相關文章
相關標籤/搜索