Tambahkan toples ke Spark Job - spark-submit

158

Benar ... sudah banyak dibahas.

Namun ada banyak ambiguitas dan beberapa jawaban yang diberikan ... termasuk duplikat referensi jar di guci / pelaksana / konfigurasi driver atau opsi.

Detail yang ambigu dan / atau dihilangkan

Rincian ambiguitas, tidak jelas, dan / atau dihilangkan berikut ini harus diklarifikasi untuk setiap opsi:

  • Bagaimana ClassPath terpengaruh
    • Sopir
    • Pelaksana (untuk tugas yang sedang berjalan)
    • Kedua
    • tidak semuanya
  • Karakter pemisahan: koma, titik dua, titik koma
  • Jika file yang disediakan didistribusikan secara otomatis
    • untuk tugas-tugas (untuk setiap pelaksana)
    • untuk Driver jarak jauh (jika dijalankan dalam mode cluster)
  • jenis URI yang diterima: file lokal, hdfs, http, dll
  • Jika disalin ke lokasi umum, di mana lokasi itu (hdfs, lokal?)

Opsi yang mempengaruhi:

  1. --jars
  2. SparkContext.addJar(...) metode
  3. SparkContext.addFile(...) metode
  4. --conf spark.driver.extraClassPath=... atau --driver-class-path ...
  5. --conf spark.driver.extraLibraryPath=..., atau --driver-library-path ...
  6. --conf spark.executor.extraClassPath=...
  7. --conf spark.executor.extraLibraryPath=...
  8. jangan lupa, parameter terakhir dari spark-submit juga file .jar.

Saya tahu di mana saya dapat menemukan dokumentasi percikan utama , dan secara khusus tentang cara mengirim , opsi yang tersedia, dan juga JavaDoc . Namun yang tersisa untuk saya masih beberapa lubang, meskipun itu menjawab sebagian juga.

Saya harap ini tidak terlalu rumit, dan seseorang dapat memberi saya jawaban yang jelas dan ringkas.

Jika saya harus menebak dari dokumentasi, tampaknya --jars, dan SparkContext addJardan addFilemetode adalah orang-orang yang secara otomatis akan mendistribusikan file, sementara pilihan lain hanya memodifikasi ClassPath tersebut.

Apakah aman untuk berasumsi bahwa untuk kesederhanaan, saya dapat menambahkan file jar aplikasi tambahan menggunakan 3 opsi utama secara bersamaan:

spark-submit --jar additional1.jar,additional2.jar \
  --driver-library-path additional1.jar:additional2.jar \
  --conf spark.executor.extraLibraryPath=additional1.jar:additional2.jar \
  --class MyClass main-application.jar

Menemukan artikel yang bagus tentang jawaban untuk posting lain . Namun tidak ada yang baru dipelajari. Poster memang membuat pernyataan yang baik tentang perbedaan antara driver lokal (klien benang) dan Remote Driver (kluster benang). Jelas penting untuk diingat.

YoYo
sumber
1
Cluster manager mana yang Anda jalankan? Standalone / BENANG / Mesos?
Yuval Itzchakov
Apa saja. Saya bermaksud ini sebagai klarifikasi ke dokumentasi asli. Saya sebagian besar menggunakan cluster mandiri, contoh tunggal, klien benang, cluster benang. Orang lain mungkin menggunakan Mesos. Tampaknya Anda melakukan riset orisinal yang bagus di blog Anda tentang hal ini. Saya akhirnya melakukan sebagian besar sama seperti Anda - menggunakan shader untuk membuat toples Uber untuk menyederhanakan proses penyebaran saya.
YoYo
1
Saya akan memposting jawaban mengenai bagaimana kami menggunakan Spark Standalone, yang dapat menghapus beberapa hal.
Yuval Itzchakov
6
Saya telah berusaha menjawab semua pertanyaan Anda. Semoga membantu :)
Yuval Itzchakov
@Yuval Itzchakov, seperti yang Yoyo sebutkan, saya juga menggunakan toples yang diarsir untuk menggabungkan semua dependensi saya, misalnya kelas kasus, dan toples lain yang mungkin saya gunakan. Saya mencoba memahami kapan saya akan mengalami situasi di mana saya perlu beberapa stoples. Maksudku, aku selalu bisa menggabungkan beberapa toples itu menjadi 1 toples uber. Mengapa saya tidak bisa terus hidup dengan toples berbayang saya mengikat semua dependensi saya?
Sheel Pancholi

Jawaban:

177

ClassPath:

ClassPath dipengaruhi tergantung pada apa yang Anda berikan. Ada beberapa cara untuk mengatur sesuatu di classpath:

  • spark.driver.extraClassPathatau alias --driver-class-pathuntuk mengatur classpath tambahan pada node yang menjalankan driver.
  • spark.executor.extraClassPath untuk mengatur jalur kelas tambahan pada node Pekerja.

Jika Anda ingin JAR tertentu dilakukan pada Master dan Pekerja, Anda harus menentukan ini secara terpisah di KEDUA bendera.

Karakter pemisahan:

Mengikuti aturan yang sama dengan JVM :

  • Linux: Titik dua :
    • misalnya: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar:/opt/prog/aws-java-sdk-1.10.50.jar"
  • Windows: Tanda titik koma ;
    • misalnya: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar;/opt/prog/aws-java-sdk-1.10.50.jar"

Distribusi file:

Ini tergantung pada mode di mana Anda menjalankan pekerjaan Anda:

  1. Mode klien - Spark meluncurkan server Netty HTTP yang mendistribusikan file saat start up untuk masing-masing node pekerja. Anda dapat melihatnya saat memulai pekerjaan Spark Anda:

    16/05/08 17:29:12 INFO HttpFileServer: HTTP File server directory is /tmp/spark-48911afa-db63-4ffc-a298-015e8b96bc55/httpd-84ae312b-5863-4f4c-a1ea-537bfca2bc2b
    16/05/08 17:29:12 INFO HttpServer: Starting HTTP Server
    16/05/08 17:29:12 INFO Utils: Successfully started service 'HTTP file server' on port 58922.
    16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/foo.jar at http://***:58922/jars/com.mycode.jar with timestamp 1462728552732
    16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/aws-java-sdk-1.10.50.jar at http://***:58922/jars/aws-java-sdk-1.10.50.jar with timestamp 1462728552767
  2. Mode Cluster - Dalam mode cluster percikan memilih simpul Worker pemimpin untuk menjalankan proses Driver aktif. Ini berarti pekerjaan tidak berjalan langsung dari node Master. Di sini, Spark tidak akan menetapkan server HTTP. Anda harus secara manual membuat JARS Anda tersedia untuk semua node pekerja melalui HDFS / S3 / Sumber lain yang tersedia untuk semua node.

URI yang diterima untuk file

Dalam "Mengirimkan Aplikasi" , dokumentasi Spark melakukan pekerjaan yang baik untuk menjelaskan awalan yang diterima untuk file:

Saat menggunakan percikan-kirim, tabung aplikasi beserta semua toples yang disertakan dengan opsi - toples akan ditransfer secara otomatis ke cluster. Spark menggunakan skema URL berikut untuk memungkinkan berbagai strategi untuk menyebar guci:

  • file: - Path absolut dan file: / URI dilayani oleh server file HTTP driver, dan setiap pelaksana menarik file dari server HTTP driver.
  • hdfs :, http :, https :, ftp: - ini merobohkan file dan JAR dari URI seperti yang diharapkan
  • local: - URI dimulai dengan local: / diharapkan ada sebagai file lokal pada setiap node pekerja. Ini berarti bahwa tidak ada IO jaringan yang akan terjadi, dan berfungsi dengan baik untuk file besar / JAR yang didorong ke setiap pekerja, atau dibagikan melalui NFS, GlusterFS, dll.

Perhatikan bahwa JAR dan file disalin ke direktori yang berfungsi untuk setiap SparkContext pada node pelaksana.

Seperti dicatat, JAR disalin ke direktori kerja untuk setiap simpul Pekerja. Di mana tepatnya itu? Hal ini biasanya di bawah /var/run/spark/work, Anda akan melihat mereka seperti ini:

drwxr-xr-x    3 spark spark   4096 May 15 06:16 app-20160515061614-0027
drwxr-xr-x    3 spark spark   4096 May 15 07:04 app-20160515070442-0028
drwxr-xr-x    3 spark spark   4096 May 15 07:18 app-20160515071819-0029
drwxr-xr-x    3 spark spark   4096 May 15 07:38 app-20160515073852-0030
drwxr-xr-x    3 spark spark   4096 May 15 08:13 app-20160515081350-0031
drwxr-xr-x    3 spark spark   4096 May 18 17:20 app-20160518172020-0032
drwxr-xr-x    3 spark spark   4096 May 18 17:20 app-20160518172045-0033

Dan ketika Anda melihat ke dalam, Anda akan melihat semua JAR yang Anda gunakan:

[*@*]$ cd /var/run/spark/work/app-20160508173423-0014/1/
[*@*]$ ll
total 89988
-rwxr-xr-x 1 spark spark   801117 May  8 17:34 awscala_2.10-0.5.5.jar
-rwxr-xr-x 1 spark spark 29558264 May  8 17:34 aws-java-sdk-1.10.50.jar
-rwxr-xr-x 1 spark spark 59466931 May  8 17:34 com.mycode.code.jar
-rwxr-xr-x 1 spark spark  2308517 May  8 17:34 guava-19.0.jar
-rw-r--r-- 1 spark spark      457 May  8 17:34 stderr
-rw-r--r-- 1 spark spark        0 May  8 17:34 stdout

Opsi yang terpengaruh:

Hal yang paling penting untuk dipahami adalah prioritas . Jika Anda melewatkan properti apa pun melalui kode, itu akan lebih diutamakan daripada opsi yang Anda tentukan melalui spark-submit. Ini disebutkan dalam dokumentasi Spark:

Nilai apa pun yang ditentukan sebagai flag atau dalam file properti akan diteruskan ke aplikasi dan digabungkan dengan yang ditentukan melalui SparkConf. Properti yang disetel langsung pada SparkConf diutamakan , kemudian flag yang dikirimkan ke spark-submit atau spark-shell, lalu opsi di file spark-defaults.conf

Jadi pastikan Anda menetapkan nilai-nilai itu di tempat yang tepat, sehingga Anda tidak akan terkejut ketika salah satu mengambil prioritas di atas yang lain.

Mari kita menganalisis setiap opsi yang dipertanyakan:

  • --jarsvs SparkContext.addJar: Ini identik, hanya satu yang ditetapkan melalui kiriman kirim dan satu melalui kode. Pilih yang cocok dengan Anda. Satu hal penting yang perlu diperhatikan adalah bahwa menggunakan salah satu dari opsi ini tidak menambahkan JAR ke driver / executor classpath Anda, Anda harus menambahkannya secara eksplisit menggunakan extraClassPathkonfigurasi pada keduanya.
  • SparkContext.addJarvs SparkContext.addFile: Gunakan yang pertama ketika Anda memiliki ketergantungan yang perlu digunakan dengan kode Anda. Gunakan yang terakhir ketika Anda hanya ingin meneruskan file sewenang-wenang ke node pekerja Anda, yang bukan ketergantungan run-time dalam kode Anda.
  • --conf spark.driver.extraClassPath=...atau --driver-class-path: Ini alias, tidak masalah yang mana yang Anda pilih
  • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ... Sama seperti di atas, alias.
  • --conf spark.executor.extraClassPath=...: Gunakan ini ketika Anda memiliki dependensi yang tidak dapat dimasukkan dalam JAR uber (misalnya, karena ada konflik waktu kompilasi antara versi pustaka) dan yang Anda perlu memuat saat runtime.
  • --conf spark.executor.extraLibraryPath=...Ini dilewatkan sebagai java.library.pathopsi untuk JVM. Gunakan ini ketika Anda membutuhkan jalur pustaka yang terlihat oleh JVM.

Apakah aman untuk berasumsi bahwa untuk kesederhanaan, saya dapat menambahkan file jar aplikasi tambahan menggunakan 3 opsi utama secara bersamaan:

Anda dapat dengan aman menganggap ini hanya untuk mode Klien, bukan mode Cluster. Seperti yang saya katakan sebelumnya. Juga, contoh yang Anda berikan memiliki beberapa argumen yang berlebihan. Misalnya, meneruskan JAR --driver-library-pathtidak berguna, Anda perlu meneruskannya extraClassPathjika Anda ingin mereka berada di jalur kelas Anda. Pada akhirnya, apa yang ingin Anda lakukan ketika Anda menggunakan JAR eksternal pada pengemudi dan pekerja adalah:

spark-submit --jars additional1.jar,additional2.jar \
  --driver-class-path additional1.jar:additional2.jar \
  --conf spark.executor.extraClassPath=additional1.jar:additional2.jar \
  --class MyClass main-application.jar
Yuval Itzchakov
sumber
4
Jawaban yang bagus dan komprehensif. Terima kasih. Bisakah Anda memberi tahu lebih banyak tentang praktik terbaik dalam penerapan dengan uber JAR vs dependensi di luar JAR (libs di folder eksternal dan tercantum dalam MANIFEST.MFfile)?
jsosnowski
2
@ jsosnowski Biasanya, saya hanya menunda untuk menggunakan guci eksternal ketika ada konflik yang sangat kompleks untuk diselesaikan dengan JAR uber saya. Saya biasanya mendapatkan hanya dengan menggunakan SBT assemblyMergeStrategydan memilih kelas yang saya butuhkan jika ada konflik. Saya biasanya akan merekomendasikan hal yang sama.
Yuval Itzchakov
9
@ yuval-itzchakov Terima kasih atas jawaban yang bagus, sangat membantu. Satu hal yang ingin saya tekankan untuk membantu orang lain yang mungkin telah melakukan kesalahan yang sama seperti saya. Argumen --jars hanya mengangkut guci ke setiap mesin di cluster. TIDAK memberitahu percikan untuk menggunakannya dalam pencarian jalur kelas. --Driver-class-path (atau argumen atau parameter konfigurasi serupa) juga diperlukan. Awalnya saya pikir mereka adalah cara alternatif untuk melakukan hal yang sama.
Tim Ryan
1
@TimRyan Pasti. Jika Anda melihat bagian terakhir dari jawaban, saya memberikan toples ke --jarsflag dan jalur kelas driver / executor.
Yuval Itzchakov
1
Akhirnya saya menemukan cara untuk menyuntikkan variabel lingkungan ke dalam zeppelin-env.shdan ditambahkan --jarske SPARK_SUBMIT_OPTIONS. Itu berhasil. Format URI yang saya gunakan adalah --jars=local:///mnt/dir/file.jar.
Mike
4

Pendekatan lain spark 2.1.0adalah dengan menggunakan --conf spark.driver.userClassPathFirst=trueselama spark-submit yang mengubah prioritas beban dependensi, dan dengan demikian perilaku pekerjaan percikan, dengan memberikan prioritas kepada guci yang ditambahkan pengguna ke jalur kelas dengan --jarsopsi.

Stanislav
sumber
2
Anda harus berhati-hati dengan itu - karena mungkin untuk memecah percikan melakukannya. Ini harus menjadi solusi opsi terakhir. Berpotensi itu dapat mengganggu lapisan yang berinteraksi dengan benang juga ketika menggunakan dalam mode benang-klien, meskipun saya tidak yakin.
YoYo
Terima kasih atas perhatiannya. Apakah ada cara untuk memprioritaskan hanya 1 toples, yang pasti ada di server dalam versi yang lebih lama tetapi Anda tidak dapat secara fisik mengganti dan Anda tahu Anda tidak ingin menggunakan?
Stanislav
1
Saya kira dalam hal ini Anda bisa mencoba persis seperti yang Anda sarankan. Tidak mengatakan itu mutlak tidak. Juga keberatan bahwa opsi ini ditandai sebagai 'percobaan' - peringatan yang harus diperhatikan! Tidak ada cara yang aman untuk memprioritaskan satu versi perpustakaan di atas yang lain. Dalam beberapa implementasi, ini diselesaikan dengan memindahkan salah satu pustaka di ruang nama yang berbeda, sehingga Anda dapat menggunakan kedua versi pada saat yang sama.
YoYo
1

Opsi Spark yang dapat dikonfigurasi lainnya yang berkaitan dengan guci dan classpath, dalam hal yarnmode penyebaran adalah sebagai berikut
Dari dokumentasi percikan,

spark.yarn.jars

Daftar perpustakaan yang berisi kode Spark untuk didistribusikan ke wadah BENANG. Secara default, Spark on YARN akan menggunakan toples Spark yang dipasang secara lokal, tetapi toples Spark juga bisa berada di lokasi yang dapat dibaca dunia di HDFS. Ini memungkinkan BENANG untuk men-cache-nya pada node sehingga tidak perlu didistribusikan setiap kali aplikasi dijalankan. Untuk menunjuk ke toples di HDFS, misalnya, atur konfigurasi ini ke hdfs: /// some / path. Gumpalan diizinkan.

spark.yarn.archive

Arsip yang berisi toples Spark yang diperlukan untuk distribusi ke cache YARN. Jika diatur, konfigurasi ini menggantikan spark.yarn.jars dan arsip digunakan di semua wadah aplikasi. Arsip harus berisi file jar di direktori root. Seperti dengan opsi sebelumnya, arsip juga dapat di-host di HDFS untuk mempercepat distribusi file.

Pengguna dapat mengkonfigurasi parameter ini untuk menentukan guci mereka, yang inturn akan dimasukkan dalam classpath driver Spark.

DaRkMaN
sumber
1

Saat menggunakan percikan-kirim dengan -master thread-cluster, stoples aplikasi beserta semua toples yang disertakan dengan opsi - toples akan secara otomatis ditransfer ke cluster. URL yang diberikan setelah - jar harus dipisahkan dengan koma. Daftar itu termasuk dalam classpath driver dan executor

Contoh:

percikan-kirim - master thread-cluster --jars ../lib/misc.jar, ../lib/test.jar --class MainClass MainApp.jar

https://spark.apache.org/docs/latest/submitting-applications.html

Siwa Garg
sumber
0

Ada batasan dalam menggunakan --jars: jika Anda ingin menentukan direktori untuk lokasi jar/xmlfile, itu tidak memungkinkan ekspansi direktori. Ini berarti jika Anda perlu menentukan jalur absolut untuk setiap toples.

Jika Anda menentukan --driver-class-pathdan Anda mengeksekusi dalam mode cluster yarn, maka kelas driver tidak diperbarui. Kami dapat memverifikasi apakah jalur kelas diperbarui atau tidak di bawah spark ui atau server riwayat percikan di bawah lingkungan tab.

Opsi yang berhasil bagi saya untuk melewatkan stoples yang berisi ekspansi direktori dan yang bekerja dalam mode cluster benang adalah --confopsi. Lebih baik untuk melewati jalur kelas driver dan executor sebagai --conf, yang menambahkan mereka untuk memicu objek sesi itu sendiri dan jalur tersebut tercermin pada Konfigurasi Spark. Tapi Tolong pastikan untuk menempatkan stoples di jalur yang sama melintasi cluster.

spark-submit \
  --master yarn \
  --queue spark_queue \
  --deploy-mode cluster    \
  --num-executors 12 \
  --executor-memory 4g \
  --driver-memory 8g \
  --executor-cores 4 \
  --conf spark.ui.enabled=False \
  --conf spark.driver.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapred.output.dir=/tmp \
  --conf spark.executor.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapreduce.output.fileoutputformat.outputdir=/tmp
Tanveer
sumber
Selamat Tahun Baru!
YoYo
Selamat Tahun Baru YoYo
Tanveer
0

Sementara kami mengirimkan pekerjaan percikan menggunakan utilitas percikan-percikan, ada opsi --jars. Dengan menggunakan opsi ini, kita dapat mengirimkan file jar untuk memicu aplikasi.

bala
sumber
Bahwa ada —jaropsi ini disebutkan oleh poster asli, ditambah dibahas lebih detail dengan lebih dari satu jawaban. Tampaknya Anda tidak menyediakan sesuatu yang baru?
YoYo