配置相關
- settings.sh
- 功能:配置環境變量
- APP_USER/APP_GROUP:作業提交用戶和組
- JMX_PORT:java jmx端口,通常在aws或者其他容器裏打開
- INSTALL_DIR:sjs所做目錄
- LOG_DIR:日誌路徑
- PIDFILE:啓動sjs,產生pid存放的文件名
- JOBSERVER_MEMORY:啓動spark作業的driverMem
- SPARK_VERSION:指定spark版本
- SCALA_VERSION:scala版本
- SPARK_HOME、SPARK_LOG_DIR、SPARK_CONF_DIR:spark相關配置
- YARN_CONF_DIR、HADOOP_CONF_DIR:yarn配置
- local.conf
- spark.master:指定spark提交的類型,yarn-client、local[4]等
- spark.jobserver
- port:指定jobServer的啓動端口,使用此端口進行作業提交和監控等
- context-per-jvm:是否每個context都啓動一個獨立的進程
- jobdao:指定處理jobs、jars等邏輯的類
- datadao:通過
POST/data
上傳到sjs的文件存放路徑 - sqldao:當
jobdao
指定爲JobSqlDAO
時使用
- slick-driver
- jdbc-driver
- rootdir:H2 driver存放數據目錄
- jdbc:連接
- dbcp:連接池
- result-chunk-size
- 作業返回值使用分塊傳輸,每塊大小
- spark.contexts:啓動sjs自動加載的context配置
- 名字
- context-settings:啓動context,即app,相關配置
- num-cpu-cores:core個數
- memory-per-node:executor的mem,eg 512m、1G
- dependent-jar-uris:依賴的jar包,list形式,或者字符串,使用逗號隔開
- [“file:///xxx.jar”,”file:///xxx2.jar”],或者”file:///xxx.jar,file:///xxx2.jar”
- 其他的spark配置,去掉前綴spark即可
- 如:spark.speculation可配置爲speculation
- server_start.sh
- 啓動spark job server
- manager_start.sh
- context-per-jvm設置爲true時,纔會使用此腳本,用於啓動context
使用
- 啓動
- 運行腳本server_start.sh即可
- 初始化context
curl -d "" 'ip:port/contexts/roncen_test_context?context-factory=spark.jobserver.context.HiveContextFactory'
- 上傳jar包
curl -H "Content-Type: application/java-archive" --data-binary @/home/vipshop/platform/sjs_2.0/jars/job-server-extras_2.11-0.7.0-SNAPSHOT.jar ip:8091/binaries/sql
- 提交作業
curl -d "sql_file=\"hdfs://bipcluster/spark/sql/test_cassandra.sql\"" 'ip:8091/jobs?appName=sql&classPath=spark.jobserver.vip.VipHiveJob&context=roncen_test_context&sync=false'
- 通過jobId獲取job運行狀態
curl -v 'ip:8091/jobs/xxx
- 刪除context
curl -X DELETE "ip:8091/contexts/roncen_test_context"
問題記錄
- server返回失敗問題
- [delete context時,context上的job並未結束]
- 時不時返回
The server was not able to produce a timely response to your request
問題1:The server was not able to produce a timely response to your request
- 探測方法
curl -v 'ip:port/jobs/b2ee01d2-a495-43a3-a0e5-f2ba82330211'
- 探測對應的jobId狀態
- 正常情況下,返回:”RUNNING”|”ERROR”|”FINISHED”
- 獲取job狀態邏輯
spark.jobserver.WebApi
中接收http的GET請求GET /jobs/<jobId>
- 通過akka從
jobInfoActor
中獲取job狀態GetJobStatus(jobId)
- 從
jobDao
中獲取對應jobId的信息
JobSqlDao.getJobInfo()
中,從數據庫中查詢對應job的信息,返回
- 從
- 返回格式
application/json
給客戶端
- jobId不存在:返回
No such job ID xxxx
- 存在:
- 構造返回格式:
jobId: , startTime: , classPath: , context: , duration: , status:
- 通過akka從
JobInfoActor
中獲取job結果GetJobResult
- 通過
AkkaClusterSupervisorActor
的GetResultActor(context)
得到對應的resultActor
- 通過contextName得到對應的resultActor -
- 通過
resultActor
的GetJobResult(jobId)
得到最後的結果
- 通過
- 返回客戶端結果
- 構造返回格式:
- jobId不存在:返回
初始化context步驟
- 命令示例
curl -d "" 'ip:port/contexts/sql-context-for-update-on-sale-85?context-factory=spark.jobserver.context.HiveContextFactory'
- 通過http調用
WebApi
中的POST /contexts/<contextName>
通過akka調用
AkkaClusterSupervisorActor
的AddContext(cName, config)
- 判斷是否存在,如果存在則返回
ContextAlreadyExists
調用方法
startContext()
- 生成contextActorName,”jobManager-” + uuid
- 在${LOG_DIR}路徑下創建contextDir路徑,生成對應文件
context.conf
- 存放
actorname
、context-factory
等基礎信息
- 存放
- 生成執行命令:
${deploy.manager-start-cmd} contextDir cluster.selfAddress(akka地址)
,即./manager_start.sh xxx
,此命令是在後臺執行的,命令後有&
- 判斷返回值,如果失敗,返回
ContextInitError
,如果成功,將其放入contextInitInfos
的map中 - 執行上述生成的命令
- 執行主類
spark.jobserver.JobManager
- 獲取
context.conf
文件中的配置信息 - 初始化jobDao,
spark.jobserver.jobdao
配置,這裏爲spark.jobserver.io.JobSqlDAO
- 初始化JobDAOActor,命名爲
dao-manager-jobmanager
- 初始化jobManager,命名爲
${context.actorname}
- join到cluster中
Cluster(system).join(clusterAddress)
????
- 發送
ActorIdentity(memberActors, actorRefOpt)
到AkkaClusterSupervisorActor
- 發送
- 執行主類
AkkaClusterSupervisorActor
收到此消息後
- 遍歷當前cluster所有的actorRef
- 如果返回的actorName以
jobManager
開頭則執行以下步驟,否則不處理 - 從
contextInitInfos
中remove當前actorName對應的actor - 執行方法
initContext()
- 初始化
JobResultActor resultActor
- 通過akka將
resultActor
發送給正在處理的actor,即發送消息JobManagerActor.Initialize(Some(resultActor))
到JobManagerActor
JobManagerActor
得到消息後,進行如下處理
- 初始化
JobStatusActor
- 得到
JobResultActor
,如果resultActor
沒有,則初始化一個 - 加載
dependent-jar-uris
指定的jar包 - 生成contextFactory,生成context
- 生成
JobCacheImpl
,用於緩存job信息 - 將
dependent-jar-uris
指定的jar包放入sparkContext.addJar()中 - 返回
Initialized(contextName, resultActor)
,如果失敗,則返回InitError(t)
- 初始化
- 得到返回值
- 如果成功,則將當前context放到
contexts
中,即contexts(ctxName) = (ref, resActor)
- 如果成功,則將當前context放到
- 如果返回的actorName以
- 遍歷當前cluster所有的actorRef
返回成功/失敗
- 判斷是否存在,如果存在則返回
- 返回json類型結果
提交job到context中
- 命令示例:
curl -d "sql = \"show databases\"" 'ip:port/jobs?appName=sql&classPath=spark.jobserver.HiveTestJob&context=sql-context-for-gs-sku-check-85&sync=true'
- 通過http調用
WebApi
中的POST /jobs
- 通過akka中
AkkaClusterSupervisorActor
的GetContext(name)
,得到對應context的jobManager
- 如果沒有得到,則返回
NoSuchContext
或者ContextInitError(err)
- 通過
jobManager
進行與context進程通信,發送JobManagerActor.StartJob
,用於提交作業
- 加載未加載的jar包
- 調用
startJobInternal()
- 通過jobSqlDao,獲取當前appName上次提交作業的時間和type,如果沒有則返回錯誤
- 隨機生成randomUUID,作爲jobId
- 通過
sparkContextFactory.loadAndValidateJob()
生成jobContainer
- 通過classPath/appname,在
JobCacheImpl
中獲取JobJarInfo
,並初始化
- 如果cache中沒有,會通過akka發送消息
GetBinaryPath()
,從jobSqlDao中獲取jar包 - 初始化構造函數,將其放入JobContainer中,返回
- 如果cache中沒有,會通過akka發送消息
- 通過classPath/appname,在
- 判斷返回值,如果爲Good(container),則繼續,否則返回錯誤
- 將結果發送給
JobResultActor
和JobStatusActor
JobStatusActor
- 發送消息
SaveJobInfo
到jobSqlDao,將信息存入元數據庫
- 發送消息
- 調用方法
getJobFuture()
返回結果
- 判斷當前runningJob是否大於最大運行job,如果是則返回
NoJobSlotsAvailable(maxRunningJobs)
,否則繼續 - 使用scala的Future,另起線程執行job
- 設置SparkEnv
- 發送消息
JobInit
到JobStatusActor
- 通過方法
HiveTestJob.validate()
判斷當前job是否正常
- 如果正常
- 發送消息
JobStarted
到JobStatusActor
- 設置sparkContext的jobGroup爲當前jobId,
sc.setJobGroup(jobId, xxx)
- 調用接口,執行job,
HiveTestJob.runJob(jobC, jobEnv, jobData)
- 發送消息
- 否則發送
JobValidationFailed
- 如果正常
- 線程執行結束
- 成功
- 發送
JobFinished
到JobStatusActor
- 發送
JobResult
到JobResultActor
- 發送
- 失敗
- 發送
JobErroredOut
到JobStatusActor
- 發送
- 成功
- 判斷當前runningJob是否大於最大運行job,如果是則返回
- 判斷返回結果,並返回給客戶端對應的http reponse
JobResult(jobId, res)
JobErroredOut
JobStarted(_, jobInfo)
- 通過akka發送給
JobInfoActor
消息StoreJobConfig(jobInfo.jobId, postedJobConfig)
JobInfoActor
得到消息後,通過jobDao.saveJobConfig(jobId, jobConfig)
存儲信息,這裏爲JobSqlDao
- 通過akka發送給
JobValidationFailed
NoSuchApplication
NoSuchClass
WrongJobType
WrongJobType
NoJobSlotsAvailable
ContextInitError
- 如果沒有得到,則返回