Seluruh skrip pada jalur ini dijalankan melalui python3, dan cara itu sah untuk pembelajaran di satu mesin. Aplikasi produksi menyusuri jalur yang berbeda, yaitu spark-submit, peluncur resmi Spark yang mengirim aplikasi ke cluster, mengatur sumber daya, dan meneruskan konfigurasi tanpa menyentuh kode. Topik ini memeragakan pengiriman tersebut pada mode lokal, beserta dua kanal konfigurasi yang paling sering membingungkan pemula, yaitu opsi --conf dan argumen aplikasi.
Aplikasi yang siap dikirim#
Aplikasi yang layak dikirim ke cluster punya dua sifat. Pertama, ia membaca parameter dari luar alih-alih mengandalkan nilai yang tertulis langsung di dalam kode, karena di cluster yang sama sering berjalan beberapa varian pekerjaan. Kedua, ia tetap bekerja ketika diberi konfigurasi yang tidak ia kenal, karena peluncur boleh menyuntikkan konfigurasi kapan saja. Skrip berikut mencontohkan keduanya dengan mengambil nama aplikasi dan jumlah partisi shuffle dari argumen baris perintah, lengkap dengan nilai bawaan untuk dijalankan tanpa argumen.
import sys
from pyspark.sql import SparkSession
nama = sys.argv[1] if len(sys.argv) > 1 else "pengiriman-lokal"
partisi = sys.argv[2] if len(sys.argv) > 2 else "2"
spark = (
SparkSession.builder
.master("local[2]")
.appName(nama)
.config("spark.sql.shuffle.partitions", partisi)
.getOrCreate()
)
data = [
("kamar1", 28.0),
("kamar2", 31.5),
("kamar1", 29.5),
("kamar2", 30.0),
]
df = spark.createDataFrame(data, "kamar string, suhu double")
print("=== identitas aplikasi ===")
print("appName :", spark.conf.get("spark.app.name"))
print("master :", spark.conf.get("spark.master"))
print("shuffle part. :", spark.conf.get("spark.sql.shuffle.partitions"))
print("=== baris dengan suhu di atas 29 ===")
df.filter("suhu > 29").show()
spark.stop()WARNING: Using incubator modules: jdk.incubator.vector
=== identitas aplikasi ===
appName : pengiriman-lokal
master : local[2]
shuffle part. : 2
=== baris dengan suhu di atas 29 ===
+------+----+
| kamar|suhu|
+------+----+
|kamar2|31.5|
|kamar1|29.5|
|kamar2|30.0|
+------+----+Ketika dijalankan tanpa argumen, aplikasi mengambil kedua nilai bawaan, sehingga identitas dan konfigurasi tercetak sesuai asalnya. Perhatikan bahwa appName pada keluaran adalah pengiriman-lokal, bukan teks yang ditulis langsung pada builder, karena argumen baris perintah diproses sebelum sesi dibangun. Pola membaca sys.argv ini sederhana tetapi menjadi dasar bagi hampir semua aplikasi Spark yang nyata.
Mengirim melalui spark-submit#
Perintah spark-submit mengambil opsi-opsi peluncur terlebih dahulu, lalu nama berkas aplikasi, lalu argumen aplikasi. Urutan ini penting, karena segala sesuatu yang ditulis setelah nama berkas menjadi milik aplikasi, bukan milik peluncur, dan opsi yang salah tempat nyaris tidak pernah memunculkan error. Perintah pertama di bawah ini menempatkan opsi --conf pada posisi yang benar untuk menunjukkan bagaimana Spark memperlakukannya.
spark-submit --conf spark.sql.shuffle.partitions=4 aplikasi.py kirim-lewat-submitWARNING: Using incubator modules: jdk.incubator.vector
=== identitas aplikasi ===
appName : kirim-lewat-submit
master : local[2]
shuffle part. : 2
=== baris dengan suhu di atas 29 ===
+------+----+
| kamar|suhu|
+------+----+
|kamar2|31.5|
|kamar1|29.5|
|kamar2|30.0|
+------+----+Opsi --conf diteruskan dengan benar ke Spark, tetapi jumlah partisi yang tercetak tetap 2, karena aplikasi memanggil .config("spark.sql.shuffle.partitions", partisi) di dalam builder dan konfigurasi yang ditulis program selalu menimpa nilai dari peluncur. Pelajaran kedua berasal dari percobaan yang gagal, yaitu ketika opsi ditulis setelah nama berkas, misalnya spark-submit aplikasi.py kirim-lewat-submit --conf spark.sql.shuffle.partitions=4, karena teks --conf jatuh ke sys.argv aplikasi dan menjadi nilai konfigurasi yang memicu error tipe saat aplikasi menyusun sesi. Inilah sebabnya parameter yang wajib mengikuti pengirim sebaiknya disalurkan melalui argumen aplikasi, bukan melalui --conf.
Argumen aplikasi sebagai kanal parameter#
Perintah berikut memperbaiki urutannya dan menyalurkan jumlah partisi melalui argumen aplikasi, yang dibaca oleh sys.argv pada awal skrip.
spark-submit aplikasi.py kirim-lewat-submit 4WARNING: Using incubator modules: jdk.incubator.vector
=== identitas aplikasi ===
appName : kirim-lewat-submit
master : local[2]
shuffle part. : 4
=== baris dengan suhu di atas 29 ===
+------+----+
| kamar|suhu|
+------+----+
|kamar2|31.5|
|kamar1|29.5|
|kamar2|30.0|
+------+----+Kali ini jumlah partisi tercetak 4, karena nilai itu berasal dari argumen aplikasi yang menjadi isi .config() di dalam kode. Pada cluster sungguhan, bentuk perintahnya tetap sama, hanya opsi peluncurnya bertambah, misalnya --master yarn atau --master k8s://, --deploy-mode cluster untuk menjalankan driver di dalam cluster alih-alih di mesin pengirim, serta --num-executors dan --executor-memory untuk mengatur sumber daya. Mode lokal yang dipakai pada seluruh jalur ini adalah kasus khusus dari schema yang sama, yaitu cluster berukuran satu mesin.
Bentuk perintah pada cluster nyata memperpanjang pola yang sama dengan opsi sumber daya. Perintah pengiriman pada tim yang menjalankan YARN, misalnya, memuat opsi-opsi di atas ditambah --executor-cores sebelum nama berkas aplikasi, sedangkan identitas berkas data berpindah ke jalur penyimpanan bersama seperti HDFS atau object storage. Aplikasi contoh topik ini dapat dikirim ke cluster semacam itu tanpa satu pun perubahan kode, dan hanya konfigurasi master beserta jalur yang disesuaikan. Kesinambungan inilah alasan mode lokal di jalur ini layak diperlakukan sungguh-sungguh, karena kebiasaan yang terbentuk di sini berpindah ke cluster tanpa diterjemahkan ulang.
Kesalahan umum#
Kesalahan pertama adalah menaruh opsi peluncur setelah nama berkas aplikasi, sebagaimana ditunjukkan perintah pertama di atas. Aplikasi bisa saja tetap berjalan tanpa error sementara opsi itu hilang, atau lebih buruk, argumen aplikasi menerima teks --conf dan menimbulkan error konfigurasi yang membingungkan. Kebiasaan yang aman adalah menulis seluruh opsi peluncur terlebih dahulu, lalu nama berkas, lalu argumen.
Kesalahan kedua adalah mengira --conf selalu menang atas kode. Apabila kode sudah memanggil .config() dengan nilai yang sama, nilai dari peluncur hanya menjadi nilai awal yang kemudian ditimpa. Ketika sebuah konfigurasi tidak berpengaruh padahal dikirim dengan benar, periksa dahulu apakah kode aplikasi menyebutnya di dalam builder.
Kesalahan ketiga adalah memakai --deploy-mode cluster bersama skrip yang membaca berkas dari jalur lokal peluncur. Pada mode cluster, driver berpindah ke mesin lain di dalam cluster, dan jalur berkas yang berlaku adalah jalur di mesin itu, bukan di mesin pengirim. Pekerjaan yang menyebut berkas data harus memakai jalur penyimpanan yang terlihat oleh seluruh cluster, misalnya HDFS atau object storage.
Ringkasan#
spark-submitadalah peluncur resmi yang mengirim aplikasi ke cluster, dengan urutan opsi peluncur, nama berkas aplikasi, lalu argumen aplikasi.- Opsi
--confhanya berlaku bila diletakkan sebelum nama berkas, dan nilai pada.config()di dalam kode tetap menimpanya. - Argumen aplikasi melalui
sys.argvadalah kanal parameter yang selalu mengikuti pengirim, dan cocok untuk nilai yang wajib terbaca. - Mode deploy menentukan di mana driver berjalan, dan mode lokal pada jalur ini adalah kasus khusus dari schema pengiriman yang sama.
Referensi#
- Submitting Applications — Apache Spark — Panduan resmi spark-submit mencakup opsi, mode deploy, dan konfigurasi sumber daya.
- pyspark.sql.SparkSession.builder — Apache Spark — Referensi builder yang menjadi titik temu konfigurasi dari peluncur dan dari kode.
- Configuration — Apache Spark — Daftar konfigurasi Spark beserta aturan prioritas antara berkas konfigurasi, peluncur, dan kode.