release yanagishima 19.0(support sparksql)

yanagishimaというpresto web uiを作っていて気づけばhive, elasticsearchに続いてsparksqlをサポートしたので今回はその辺をちょっと書いてみようと思います。 https://github.com/yanagishima/yanagishima

sparkではspark thrift serverなるものを起動すればHive JDBC Driverを使ってsqlをsubmitすることができます。 https://spark.apache.org/docs/latest/sql-distributed-sql-engine.html

うちの環境だとsparkをyarn上で動かしています。 この場合spark thrift serverを起動すると一つのyarn applicationが立ち上がります。 このApplication Masterのリンクをクリックするとsparkのweb uiを見ることができます。 http://sparkthriftserver:4040にアクセスしても同じ。

複数のユーザがこのyarn applicationを共有する感じになります。 containerというかexecutorの数はsparkのdynamic allocationの仕組みで動いていてdefaultだとmaxでも10個のcontainerしか動かないので、うちの環境では増やしてます。 spark.dynamicAllocation.minExecutorsを50にしているので最初は50個のcontainerが動きます。 ちなみにspark thrift serverで一つ使うので合計すると51個動きます。

またspark thrift serverはdefaultだと1GBのメモリで動いていてOutOfMemoryに遭遇したので4GBに増やしました。 https://community.hortonworks.com/content/supportkb/233822/sparkthriftserver-crashing-with-java-heap-outofmem.html

うちはHDP環境なのでAmbariでSPARK_DAEMON_MEMORYをいじって設定しました。

なお僕はyanagishimaを作って運用して4年ぐらい経ちますが、この手のビッグデータを扱うsqlフロントエンドツールではジョブをsubmitして結果を表示するだけでは不十分です。

ジョブの進捗状況が見れて、クエリを途中でキャンセル出来ることが重要です。また全ジョブの実行状況が見れることも管理上必要です。

そしてつくづく分かったのはprestoはapiというかアーキテクチャからして上記の要件を実装しやすいが、他はそれが簡単ではないということです。 prestoの場合はJDBCではなくpresto-clientを使えばジョブをsubmitしてすぐにquery idを取得できます。 そしてこのquery idを使ってapiをたたけば途中の進捗状況も取れますし、クエリのキャンセルも可能です。 ジョブの一覧を見るのも容易です。

一方、Hive JDBC Driverを使うとStatement#cancelを使えばクエリのキャンセルこそできますが、進捗状況や全ジョブ一覧を知るには一工夫必要です。 Hive on MapReduceであればyarn rest apiを使えば割といろいろできますが、自分が投げたジョブがどのジョブかを判断するのは簡単ではありません。

yanagishima hiveではshibを真似してmapreduce.job.nameをいじってyanagishima-hive-wyukawa-20190305_060438_9235eaae6f11cd0ff3de907771b28914みたいなユニークなidを採番して設定してトラッキングします。 このidは自前で採番します。prestoとはここが違います。

Hive on Tezだと同じことができないので進捗状況を知ることができません。

sparksqlの場合はどうするかというとすごく泥臭いことをしました。

sparkもapiはありますが、十分ではありません。 https://spark.apache.org/docs/latest/monitoring.html https://medium.com/@an_chee/how-to-get-spark-metrics-as-json-using-spark-rest-api-in-yarn-cluster-mode-52a88002c826

sparkのjob idがわかればnumCompletedTasks / numTasksで進捗状況がわかります。 問題はどうやって知るかです。

http//[resourcemanager]:8088/proxy/[spark application id]/api/v1/applications/[spark application id]/jobs をたたけばジョブ一覧が取れます。

以下は一つのジョブの例です。

  "jobId" : 15,
  "name" : "run at AccessController.java:0",
  "submissionTime" : "2019-02-21T02:23:54.513GMT",
  "stageIds" : [ 21 ],
  "jobGroup" : "b46b9cee-bb9d-4d10-8b44-5f7328ce5748",
  "status" : "RUNNING",
  "numTasks" : 1093,
  "numActiveTasks" : 1,
  "numCompletedTasks" : 488,
  "numSkippedTasks" : 0,
  "numFailedTasks" : 0,
  "numActiveStages" : 1,
  "numCompletedStages" : 0,
  "numSkippedStages" : 0,
  "numFailedStages" : 0

これだけだと誰がどんなクエリ投げたのかわからないですが、http://sparkthriftserver:4040/sqlserverSQL StatisticsのところにUser, JobID, GroupID, Start Time, Finish Time, Duration, Statement, State, Detail があって、ここのJobIDと上記のjobGroupを紐づければ誰がどんなクエリを投げたかわかります。やったね。 だがしかしapiが無いようなので仕方なくhtml parseしました。。。

ともあれ、そんな感じで作りました。

sparkも今後rest apiが充実するといいなあというか、そういう状況だからApache Livyが存在しているという気もする。 遠い昔まだhadoop 1の時代にrest apiがなかったのでHuahin Managerがあったように。