ClassPath:
O ClassPath é afetado dependendo do que você fornece. Existem algumas maneiras de definir algo no caminho de classe:
spark.driver.extraClassPath
ou é apelido --driver-class-path
para definir caminhos de classe extras no nó que está executando o driver.
spark.executor.extraClassPath
para definir o caminho extra da classe nos nós do trabalhador.
Se você deseja que um certo JAR seja efetuado no mestre e no trabalhador, é necessário especificá-los separadamente em AMBOS os sinalizadores.
Caractere de separação:
Seguindo as mesmas regras que a JVM :
- Linux: dois pontos
:
- por exemplo:
--conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar:/opt/prog/aws-java-sdk-1.10.50.jar"
- Windows: um ponto-e-vírgula
;
- por exemplo:
--conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar;/opt/prog/aws-java-sdk-1.10.50.jar"
Distribuição de arquivos:
Isso depende do modo em que você está executando seu trabalho:
Modo cliente - O Spark aciona um servidor HTTP Netty que distribui os arquivos na inicialização de cada um dos nós do trabalhador. Você pode ver que, ao iniciar seu trabalho do 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
Modo de cluster - No modo de cluster, o spark selecionou um nó Worker líder para executar o processo do Driver. Isso significa que o trabalho não está sendo executado diretamente no nó Mestre. Aqui, o Spark não definirá um servidor HTTP. É necessário disponibilizar manualmente o seu JARS para todos os nós do trabalhador por meio de fontes HDFS / S3 / Other disponíveis para todos os nós.
URIs aceitos para arquivos
Em "Enviando aplicativos" , a documentação do Spark explica bem os prefixos aceitos para arquivos:
Ao usar o envio por spark, o jar do aplicativo, juntamente com os jars incluídos na opção --jars, será automaticamente transferido para o cluster. O Spark usa o seguinte esquema de URL para permitir estratégias diferentes para disseminar jarros:
- file: - Caminhos absolutos e file: / URIs são atendidos pelo servidor de arquivos HTTP do driver, e todo executor extrai o arquivo do servidor HTTP do driver.
- hdfs :, http :, https :, ftp: - esses arquivos e JARs suspensos do URI, conforme o esperado
- local: - espera-se que um URI que comece com local: / exista como um arquivo local em cada nó do trabalhador. Isso significa que nenhuma E / S de rede será incorrida e funciona bem para arquivos / JARs grandes enviados por cada trabalhador ou compartilhados via NFS, GlusterFS etc.
Observe que JARs e arquivos são copiados para o diretório de trabalho de cada SparkContext nos nós do executor.
Conforme observado, os JARs são copiados para o diretório de trabalho de cada nó Worker. Onde exatamente é isso? É geralmente sob /var/run/spark/work
, você vai vê-los como este:
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
E quando você olhar para dentro, verá todos os JARs implementados:
[*@*]$ 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
Opções afetadas:
A coisa mais importante a entender é a prioridade . Se você passar qualquer propriedade via código, ela terá precedência sobre qualquer opção que você especificar via spark-submit
. Isso é mencionado na documentação do Spark:
Quaisquer valores especificados como sinalizadores ou no arquivo de propriedades serão passados para o aplicativo e mesclados com os especificados por meio do SparkConf. As propriedades definidas diretamente no SparkConf têm precedência mais alta , depois os sinalizadores passados para envio de spark ou shell de spark e opções no arquivo spark-defaults.conf
Portanto, certifique-se de definir esses valores nos lugares adequados, para que você não se surpreenda quando um tiver prioridade sobre o outro.
Vamos analisar cada opção em questão:
--jars
vs SparkContext.addJar
: são idênticos, apenas um é definido através do envio de spark e outro via código. Escolha o que melhor combina com você. Uma coisa importante a ser observada é que o uso de uma dessas opções não adiciona o JAR ao caminho de classe do driver / executor , você precisará adicioná-las explicitamente usando a extraClassPath
configuração em ambas.
SparkContext.addJar
vs SparkContext.addFile
: use o primeiro quando tiver uma dependência que precise ser usada com seu código. Use o último quando quiser simplesmente passar um arquivo arbitrário para os nós do trabalhador, o que não é uma dependência em tempo de execução do seu código.
--conf spark.driver.extraClassPath=...
ou --driver-class-path
: esses são aliases, não importa qual você escolher
--conf spark.driver.extraLibraryPath=..., or --driver-library-path ...
O mesmo que acima, aliases.
--conf spark.executor.extraClassPath=...
: Use isso quando tiver uma dependência que não possa ser incluída em um JAR uber (por exemplo, porque há conflitos de tempo de compilação entre versões da biblioteca) e que você precisará carregar em tempo de execução.
--conf spark.executor.extraLibraryPath=...
Isso é passado como a java.library.path
opção para a JVM. Use isso quando precisar de um caminho de biblioteca visível para a JVM.
Seria seguro supor que, por simplicidade, eu posso adicionar arquivos jar de aplicativos adicionais usando as 3 opções principais ao mesmo tempo:
Você pode assumir isso com segurança apenas no modo Cliente, não no modo Cluster. Como eu disse anteriormente. Além disso, o exemplo que você deu possui alguns argumentos redundantes. Por exemplo, passar JARs para --driver-library-path
é inútil, você precisará passá-los extraClassPath
se quiser que eles estejam no seu caminho de classe. Por fim, o que você deseja fazer ao implantar JARs externos no driver e no trabalhador é:
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