Thêm lọ vào Công việc Spark - gửi tia lửa


158

Đúng ... nó đã được thảo luận khá nhiều.

Tuy nhiên, có rất nhiều sự mơ hồ và một số câu trả lời được cung cấp ... bao gồm các tham chiếu jar trùng lặp trong cấu hình hoặc tùy chọn trình điều khiển / tệp thực thi / trình điều khiển.

Các chi tiết mơ hồ và / hoặc bỏ qua

Sau các chi tiết không rõ ràng, không rõ ràng và / hoặc bị bỏ qua cần được làm rõ cho từng tùy chọn:

  • ClassPath bị ảnh hưởng như thế nào
    • Người lái xe
    • Executor (cho các tác vụ đang chạy)
    • Cả hai
    • không có gì
  • Ký tự phân tách: dấu phẩy, dấu hai chấm, dấu chấm phẩy
  • Nếu các tập tin được cung cấp được tự động phân phối
    • cho các nhiệm vụ (cho mỗi người thi hành)
    • cho Trình điều khiển từ xa (nếu chạy ở chế độ cụm)
  • loại URI được chấp nhận: tệp cục bộ, hdfs, http, v.v.
  • Nếu được sao chép vào một vị trí chung, vị trí đó ở đâu (hdfs, local?)

Các tùy chọn mà nó ảnh hưởng đến:

  1. --jars
  2. SparkContext.addJar(...) phương pháp
  3. SparkContext.addFile(...) phương pháp
  4. --conf spark.driver.extraClassPath=... hoặc là --driver-class-path ...
  5. --conf spark.driver.extraLibraryPath=..., hoặc là --driver-library-path ...
  6. --conf spark.executor.extraClassPath=...
  7. --conf spark.executor.extraLibraryPath=...
  8. đừng quên, tham số cuối cùng của spark-submit cũng là một tệp .jar.

Tôi biết nơi tôi có thể tìm thấy tài liệu tia lửa chính và cụ thể về cách gửi , các tùy chọn có sẵn và cả JavaDoc . Tuy nhiên, điều đó đối với tôi vẫn còn khá nhiều lỗ hổng, mặc dù nó cũng trả lời một phần.

Tôi hy vọng rằng nó không quá phức tạp và ai đó có thể cho tôi một câu trả lời rõ ràng và súc tích.

Nếu tôi được đoán từ tài liệu, có vẻ như --jars, và SparkContext addJaraddFilephương pháp là những người đó sẽ tự động phân phối tác phẩm, trong khi các tùy chọn khác chỉ đơn thuần là thay đổi classpath.

Có an toàn không khi cho rằng để đơn giản, tôi có thể thêm các tệp jar ứng dụng bổ sung bằng 3 tùy chọn chính cùng một lúc:

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

Tìm thấy một bài viết tốt đẹp về một câu trả lời cho một bài viết khác . Tuy nhiên không có gì mới học được. Các poster thực hiện một nhận xét tốt về sự khác biệt giữa Trình điều khiển cục bộ (sợi khách hàng) và Trình điều khiển từ xa (cụm sợi). Chắc chắn quan trọng để ghi nhớ.


1
Bạn đang chạy theo trình quản lý cụm nào? Độc lập / YARN / Mesos?
Yuval Itzchakov

Bất kì. Tôi dự định điều này như là một sự làm rõ cho các tài liệu ban đầu. Tôi chủ yếu sử dụng cụm độc lập, ví dụ đơn, khách hàng sợi, cụm sợi. Những người khác có thể đang sử dụng Mesos. Có vẻ như bạn đã làm một số nghiên cứu ban đầu tốt trên blog của bạn về điều này. Cuối cùng tôi đã làm giống như bạn - sử dụng trình tạo bóng để tạo một bình Uber để đơn giản hóa quy trình triển khai của tôi.
YoYo

1
Tôi sẽ đăng câu trả lời về cách chúng tôi triển khai Spark Stand Độc, có thể xóa một số điều.
Yuval Itzchakov

6
Tôi đã nỗ lực trả lời tất cả các câu hỏi của bạn. Hy vọng nó sẽ giúp :)
Yuval Itzchakov

@Yuval Itzchakov, giống như Yoyo đã đề cập, tôi cũng sử dụng một cái bóng mờ để gói tất cả các phụ thuộc của mình, ví dụ như các lớp trường hợp và các lọ khác mà tôi có thể đang sử dụng. Tôi đang cố gắng để hiểu khi nào tôi sẽ gặp phải một tình huống mà tôi cần nhiều lọ. Ý tôi là tôi luôn có thể bó nhiều lọ đó vào 1 bình uber. Tại sao tôi không thể tiếp tục sống với những chiếc lọ bóng mờ của mình bó lại tất cả các phụ thuộc của tôi?
Sheel Pancholi

Câu trả lời:


177

ClassPath:

ClassPath bị ảnh hưởng tùy thuộc vào những gì bạn cung cấp. Có một vài cách để thiết lập một cái gì đó trên đường dẫn:

  • spark.driver.extraClassPathhoặc là bí danh --driver-class-pathđể đặt các đường dẫn lớp bổ sung trên nút chạy trình điều khiển.
  • spark.executor.extraClassPath để đặt đường dẫn lớp bổ sung trên các nút Công nhân.

Nếu bạn muốn một JAR nào đó được thực hiện trên cả Master và Worker, bạn phải chỉ định các JAR này một cách riêng biệt trong các cờ BÓNG.

Ký tự phân tách:

Theo các quy tắc tương tự như JVM :

  • Linux: dấu hai chấm :
    • ví dụ: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar:/opt/prog/aws-java-sdk-1.10.50.jar"
  • Windows: Dấu chấm phẩy ;
    • ví dụ: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar;/opt/prog/aws-java-sdk-1.10.50.jar"

Phân phối tệp:

Điều này phụ thuộc vào chế độ bạn đang thực hiện công việc của mình theo:

  1. Chế độ máy khách - Spark kích hoạt máy chủ Netty HTTP, phân phối các tệp khi khởi động cho mỗi nút worker. Bạn có thể thấy điều đó khi bạn bắt đầu công việc Spark:

    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. Chế độ cụm - Trong chế độ cụm, tia lửa đã chọn một nút Công nhân lãnh đạo để thực thi quy trình Trình điều khiển trên. Điều này có nghĩa là công việc không chạy trực tiếp từ nút Master. Ở đây, Spark sẽ không đặt máy chủ HTTP. Bạn phải cung cấp JARS theo cách thủ công cho tất cả các nút worker thông qua HDFS / S3 / Các nguồn khác có sẵn cho tất cả các nút.

URI được chấp nhận cho các tệp

Trong "Gửi ứng dụng" , tài liệu Spark thực hiện tốt công việc giải thích các tiền tố được chấp nhận cho các tệp:

Khi sử dụng tia lửa, bình ứng dụng cùng với bất kỳ lọ nào có trong tùy chọn --jars sẽ được tự động chuyển sang cụm. Spark sử dụng lược đồ URL sau để cho phép các chiến lược khác nhau để phổ biến các lọ:

  • tệp: - Đường dẫn và tệp tuyệt đối: / URI được phục vụ bởi máy chủ tệp HTTP của trình điều khiển và mọi người thực thi sẽ kéo tệp từ máy chủ HTTP của trình điều khiển.
  • hdfs:, http:, https:, ftp: - những tệp này kéo xuống các tệp và JAR từ URI như mong đợi
  • local: - một URI bắt đầu bằng local: / dự kiến ​​sẽ tồn tại dưới dạng tệp cục bộ trên mỗi nút worker. Điều này có nghĩa là sẽ không có IO mạng nào phát sinh và hoạt động tốt đối với các tệp / JAR lớn được đẩy đến từng nhân viên hoặc được chia sẻ qua NFS, GlusterFS, v.v.

Lưu ý rằng các tệp và tệp JAR được sao chép vào thư mục làm việc cho mỗi SparkContext trên các nút thực thi.

Như đã lưu ý, các JAR được sao chép vào thư mục làm việc cho mỗi nút Worker. Chính xác thì nó ở đâu? Nó thường ở dưới /var/run/spark/work, bạn sẽ thấy chúng như thế này:

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

Và khi bạn nhìn vào bên trong, bạn sẽ thấy tất cả các JAR bạn đã triển khai cùng:

[*@*]$ 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

Tùy chọn bị ảnh hưởng:

Điều quan trọng nhất để hiểu là ưu tiên . Nếu bạn chuyển bất kỳ thuộc tính nào qua mã, nó sẽ được ưu tiên hơn bất kỳ tùy chọn nào bạn chỉ định qua spark-submit. Điều này được đề cập trong tài liệu Spark:

Mọi giá trị được chỉ định dưới dạng cờ hoặc trong tệp thuộc tính sẽ được chuyển cho ứng dụng và được hợp nhất với các giá trị được chỉ định qua SparkConf. Các thuộc tính được đặt trực tiếp trên SparkConf được ưu tiên cao nhất , sau đó các cờ được chuyển sang spark-submit hoặc spark-shell, sau đó các tùy chọn trong tệp spark-defaults.conf

Vì vậy, hãy đảm bảo bạn đặt các giá trị đó ở những vị trí thích hợp, để bạn không ngạc nhiên khi cái này được ưu tiên hơn cái kia.

Hãy phân tích từng tùy chọn trong câu hỏi:

  • --jarsvs SparkContext.addJar: Đây là giống hệt nhau, chỉ có một được đặt thông qua tia lửa gửi và một qua mã. Chọn một trong đó bộ bạn tốt hơn. Một điều quan trọng cần lưu ý là việc sử dụng một trong hai tùy chọn này không thêm JAR vào đường dẫn trình điều khiển / trình thực thi của bạn, bạn sẽ cần thêm chúng một cách rõ ràng bằng cách sử dụng extraClassPathcấu hình trên cả hai.
  • SparkContext.addJarvs SparkContext.addFile: Sử dụng trước đây khi bạn có một phụ thuộc cần được sử dụng với mã của bạn. Sử dụng cái sau khi bạn chỉ muốn truyền một tệp tùy ý xung quanh các nút worker của bạn, đây không phải là một phụ thuộc thời gian chạy trong mã của bạn.
  • --conf spark.driver.extraClassPath=...hoặc --driver-class-path: Đây là những bí danh, không quan trọng bạn chọn cái nào
  • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ... Tương tự như trên, bí danh.
  • --conf spark.executor.extraClassPath=...: Sử dụng tùy chọn này khi bạn có một phụ thuộc không thể đưa vào JAR uber (ví dụ: vì có xung đột thời gian biên dịch giữa các phiên bản thư viện) và bạn cần tải khi chạy.
  • --conf spark.executor.extraLibraryPath=...Điều này được thông qua dưới dạng java.library.pathtùy chọn cho JVM. Sử dụng điều này khi bạn cần một đường dẫn thư viện hiển thị cho JVM.

Có an toàn không khi cho rằng để đơn giản, tôi có thể thêm các tệp jar ứng dụng bổ sung bằng 3 tùy chọn chính cùng một lúc:

Bạn chỉ có thể giả định điều này một cách an toàn cho chế độ Máy khách, không phải chế độ Cụm. Như tôi đã nói trước đây. Ngoài ra, ví dụ bạn đưa ra có một số đối số dư thừa. Ví dụ, chuyển JAR đến --driver-library-pathlà vô ích, bạn cần chuyển chúng sang extraClassPathnếu bạn muốn chúng nằm trên đường dẫn của bạn. Cuối cùng, những gì bạn muốn làm khi bạn triển khai các JAR bên ngoài trên cả trình điều khiển và công nhân là:

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

4
Câu trả lời tuyệt vời và toàn diện. Cảm ơn bạn. Bạn cũng có thể nói thêm về các thực tiễn tốt nhất khi triển khai với uber JAR so với các phụ thuộc bên ngoài JAR (libs trong thư mục bên ngoài và được liệt kê trong MANIFEST.MFtệp)?
jsosnowski

2
@jsosnowski Thông thường, tôi chỉ trì hoãn việc sử dụng các lọ bên ngoài khi có những xung đột rất phức tạp để giải quyết với JAR uber của tôi. Tôi thường nhận được bằng cách đơn giản bằng cách sử dụng SBT assemblyMergeStrategyvà chọn các lớp tôi cần nếu có xung đột. Tôi thường khuyên bạn nên như vậy.
Yuval Itzchakov

9
@ yuval-itzchakov Cảm ơn câu trả lời tuyệt vời, rất hữu ích. Một điểm tôi muốn nhấn mạnh để giúp đỡ những người khác có thể đã mắc lỗi tương tự như tôi đã làm. Đối số --jars chỉ vận chuyển các lọ đến từng máy trong cụm. Nó KHÔNG cho tia lửa sử dụng chúng trong tìm kiếm đường dẫn lớp. Đường dẫn --do-class (hoặc các đối số hoặc tham số cấu hình tương tự) cũng được yêu cầu. Ban đầu tôi nghĩ họ là những cách khác nhau để làm điều tương tự.
Tim Ryan

1
@TimRyan Chắc chắn. Nếu bạn nhìn vào phần cuối của câu trả lời, tôi chuyển các lọ cho cả --jarscờ đường dẫn lớp trình điều khiển / thực thi.
Yuval Itzchakov

1
Cuối cùng, tôi tìm thấy làm thế nào để đưa các biến môi trường vào zeppelin-env.shvà thêm --jarsvào SPARK_SUBMIT_OPTIONS. Điều đó đã làm việc. Định dạng URI tôi sử dụng là --jars=local:///mnt/dir/file.jar.
Mike

4

Một cách tiếp cận khác spark 2.1.0là sử dụng --conf spark.driver.userClassPathFirst=truetrong quá trình gửi tia lửa, thay đổi mức độ ưu tiên của tải phụ thuộc và do đó, hành vi của công việc tia lửa, bằng cách ưu tiên cho các lọ mà người dùng đang thêm vào đường dẫn lớp với --jarstùy chọn.


2
Bạn sẽ phải cẩn thận với điều đó - vì có thể phá vỡ tia lửa làm như vậy. Đây phải là một giải pháp lựa chọn cuối cùng. Có khả năng nó có thể can thiệp vào lớp giao thoa với sợi khi sử dụng ở chế độ máy khách, mặc dù tôi không chắc chắn.
YoYo

Cảm ơn bạn đã đứng đầu. Có cách nào để ưu tiên chỉ 1 jar, điều đó chắc chắn tồn tại trong máy chủ ở phiên bản cũ hơn nhưng bạn không thể thay thế về mặt vật lý và bạn biết bạn không muốn sử dụng?
Stanislav

1
Tôi đoán trong trường hợp đó bạn có thể thử chính xác như bạn đề xuất. Không nói rằng đó là một không tuyệt đối. Cũng lưu ý rằng tùy chọn được đánh dấu là 'thử nghiệm' - một cảnh báo sẽ được chú ý! Không có cách nào an toàn để ưu tiên một phiên bản của thư viện so với phiên bản khác. Trong một số triển khai, điều này được giải quyết bằng cách di chuyển một trong các thư viện trong một không gian tên khác nhau, do đó bạn có thể sử dụng cả hai phiên bản cùng một lúc.
YoYo

1

Tùy chọn Spark có thể định cấu hình khác liên quan đến bình và đường dẫn lớp, trong trường hợp yarnlà chế độ triển khai như sau
Từ tài liệu tia lửa,

spark.yarn.jars

Danh sách các thư viện chứa mã Spark để phân phối cho các thùng chứa YARN. Theo mặc định, Spark trên YARN sẽ sử dụng bình Spark được cài đặt cục bộ, nhưng bình Spark cũng có thể ở vị trí dễ đọc trên thế giới trên HDFS. Điều này cho phép YARN lưu bộ đệm vào các nút để không cần phân phối mỗi khi ứng dụng chạy. Ví dụ, để trỏ đến các tệp trên HDFS, hãy đặt cấu hình này thành hdfs: /// some / path. Quả cầu được cho phép.

spark.yarn.archive

Một kho lưu trữ chứa các bình Spark cần thiết để phân phối vào bộ đệm YARN. Nếu được đặt, cấu hình này sẽ thay thế spark.yarn.jars và kho lưu trữ được sử dụng trong tất cả các vùng chứa của ứng dụng. Các kho lưu trữ nên chứa các tập tin jar trong thư mục gốc của nó. Giống như với tùy chọn trước đó, kho lưu trữ cũng có thể được lưu trữ trên HDFS để tăng tốc độ phân phối tệp.

Người dùng có thể định cấu hình tham số này để chỉ định các lọ của họ, trong đó inturn được bao gồm trong đường dẫn lớp của trình điều khiển Spark.


1

Khi sử dụng tia lửa gửi với cụm -master sợi, bình ứng dụng cùng với bất kỳ lọ nào đi kèm với tùy chọn --jars sẽ được tự động chuyển sang cụm. Các URL được cung cấp sau --jars phải được phân tách bằng dấu phẩy. Danh sách đó được bao gồm trong các đường dẫn trình điều khiển và thực thi

Thí dụ :

spark-submit --master sợi-cluster --jars ../lib/misc.jar, ../lib/test.jar - class MainClass MainApp.jar

https://spark.apache.org/docs/latest/submmit-appluggest.html


0

Có hạn chế về việc sử dụng --jars: nếu bạn muốn chỉ định một thư mục cho vị trí của jar/xmltệp, nó không cho phép mở rộng thư mục. Điều này có nghĩa là nếu bạn cần chỉ định đường dẫn tuyệt đối cho mỗi bình.

Nếu bạn chỉ định --driver-class-pathvà bạn đang thực hiện ở chế độ cụm sợi, thì lớp trình điều khiển sẽ không được cập nhật. Chúng tôi có thể xác minh xem đường dẫn lớp có được cập nhật hay không trong máy chủ spark ui hoặc spark history trong môi trường tab.

Tùy chọn làm việc cho tôi để vượt qua các lọ chứa mở rộng thư mục và hoạt động ở chế độ cụm sợi là --conftùy chọn. Tốt hơn là vượt qua các đường dẫn lớp trình điều khiển và trình thực thi --conf, như thêm chúng vào chính đối tượng phiên Spark và các đường dẫn đó được phản ánh trên Cấu hình Spark. Nhưng hãy chắc chắn để đặt các lọ trên cùng một đường dẫn qua cụm.

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

Chúc mừng năm mới!
YoYo

Chúc mừng năm mới YoYo
Tanveer

0

Mặc dù chúng tôi gửi công việc spark bằng tiện ích spark-submit, có một tùy chọn --jars. Sử dụng tùy chọn này, chúng ta có thể truyền tệp jar cho các ứng dụng.


Rằng có —jartùy chọn này đã được đề cập bởi người đăng ban đầu, cộng với thảo luận chi tiết hơn nhiều bằng nhiều câu trả lời. Có vẻ như bạn không cung cấp bất cứ điều gì mới?
YoYo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.