Adicionar flasks a um trabalho de ignição – enviar com faísca

Verdade … foi bastante discutido.

No entanto, há muita ambigüidade e algumas das respostas fornecidas … incluindo a duplicação de referências de jar na configuração ou opções do jars / executor / driver.

Os detalhes ambíguos e / ou omitidos

Após a ambiguidade, detalhes obscuros e / ou omitidos devem ser esclarecidos para cada opção:

  • Como o ClassPath é afetado
    • Motorista
    • Executor (para tarefas em execução)
    • Ambos
    • de modo nenhum
  • Caractere de separação: vírgula, dois pontos, ponto e vírgula
  • Se os arquivos fornecidos forem distribuídos automaticamente
    • para as tarefas (para cada executor)
    • para o driver remoto (se executado no modo de cluster)
  • tipo de URI aceito: arquivo local, hdfs, http, etc
  • Se copiado em um local comum, onde esse local é (hdfs, local?)

As opções às quais isso afeta:

  1. --jars
  2. SparkContext.addJar(...)
  3. SparkContext.addFile(...)
  4. --conf spark.driver.extraClassPath=... ou --driver-class-path ...
  5. --conf spark.driver.extraLibraryPath=... , ou --driver-library-path ...
  6. --conf spark.executor.extraClassPath=...
  7. --conf spark.executor.extraLibraryPath=...
  8. para não esquecer, o último parâmetro do envio de faíscas é também um arquivo .jar.

Estou ciente de onde posso encontrar a documentação principal da ignição e, especificamente, sobre como enviar , as opções disponíveis e também o JavaDoc . Porém isso deixou para mim ainda alguns buracos, embora respondeu parcialmente também.

Espero que não seja tão complexo e que alguém possa me dar uma resposta clara e concisa.

Se eu fosse adivinhar a partir da documentação, parece que --jars , e os SparkContext addJar e addFile são os que distribuirão arquivos automaticamente, enquanto as outras opções apenas modificam o ClassPath.

Seria seguro assumir que, para simplificar, posso adicionar mais arquivos jar do aplicativo usando as 3 opções principais ao mesmo tempo:

 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 

Encontrei um artigo legal em uma resposta para outro post . No entanto, nada de novo aprendido. O pôster faz uma boa observação sobre a diferença entre o driver local (yarn-client) e o driver remoto (yarn-cluster). Definitivamente importante ter em mente.

   

ClassPath:

O ClassPath é afetado dependendo do que você fornece. Existem algumas maneiras de definir algo no caminho de class:

  • spark.driver.extraClassPath ou seu alias --driver-class-path para definir --driver-class-path de class extras no nó que está executando o driver.
  • spark.executor.extraClassPath para definir o caminho da class extra nos nós Worker.

Se você quiser que um determinado JAR seja efetuado no Master e no Worker, você deve especificá-los separadamente em BOTH flags.

Caráter de separação:

Seguindo as mesmas regras da JVM :

  • Linux: dois pontos :
    • 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 ; vírgula ;
    • 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:

  1. Modo cliente – o Spark triggers um servidor HTTP Netty que distribui os arquivos na boot de cada um dos nós do trabalhador. Você pode ver isso quando iniciar o 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 
  2. Modo de cluster – no modo de cluster, a ignição selecionou um nó de trabalho do 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 irá definir um servidor HTTP. Você precisa disponibilizar manualmente seu JARS para todo o nó do trabalhador via HDFS / S3 / Outras fonts disponíveis para todos os nós.

URIs aceitos para arquivos

Em “Enviando aplicativos” , a documentação do Spark faz um bom trabalho ao explicar os prefixos aceitos para arquivos:

Ao usar spark-submit, o jar do aplicativo junto com quaisquer jars incluídos com a opção –jars serão automaticamente transferidos para o cluster. O Spark usa o seguinte esquema de URL para permitir diferentes estratégias de disseminação de jars:

  • file: – Caminhos absolutos e file: / URIs são servidos pelo servidor de arquivos HTTP do driver, e todo executor puxa o arquivo do servidor HTTP do driver.
  • hdfs :, http :, https :, ftp: – esses arquivos suspensos e JARs do URI conforme esperado
  • local: – espera-se que um URI começando 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 grandes / JARs que são enviados para cada trabalhador ou compartilhados via NFS, GlusterFS, etc.

Observe que os arquivos e JARs são copiados para o diretório de trabalho para cada SparkContext nos nós do executor.

Conforme observado, os JARs são copiados para o diretório de trabalho para cada nó do Worker. Onde exatamente é isso? Geralmente é sob /var/run/spark/work , você os verá assim:

 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 que você implantou:

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

O mais importante é entender a prioridade . Se você passar qualquer propriedade via código, terá precedência sobre qualquer opção que você especificar através 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 aqueles especificados por meio do SparkConf. As propriedades definidas diretamente no SparkConf têm maior precedência , depois os flags são passados ​​para spark-submit ou spark-shell, e as opções no arquivo spark-defaults.conf

Portanto, certifique-se de definir esses valores nos locais apropriados, para que você não fique surpreso quando um tiver prioridade sobre o outro.

Vamos analisar cada opção em questão:

  • --jars vs SparkContext.addJar : Estes são idênticos, apenas um é definido através do envio de faísca e um via código. Escolha o que você suites melhor. Uma coisa importante a notar é que usando qualquer uma dessas opções não adiciona o JAR ao seu caminho de class do driver / executor , você precisará explicitamente adicioná-las usando a configuração extraClassPath em ambos.
  • SparkContext.addJar vs SparkContext.addFile : use o antigo quando você tiver uma dependência que precise ser usada com seu código. Use o último quando você simplesmente quiser passar um arquivo arbitrário para os nós do trabalhador, o que não é uma dependência de tempo de execução em seu código.
  • --conf spark.driver.extraClassPath=... ou --driver-class-path : São aliases, não importa qual você escolher
  • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ... mesmo que acima, aliases.
  • --conf spark.executor.extraClassPath=... : Use isto quando você tem uma dependência que não pode ser incluída em um JAR uber (por exemplo, porque existem conflitos de tempo de compilation entre versões de bibliotecas) e quais você precisa carregar em tempo de execução.
  • --conf spark.executor.extraLibraryPath=... Isso é passado como a opção java.library.path para a JVM. Use isso quando você precisar de um caminho de biblioteca visível para a JVM.

Seria seguro assumir que, para simplificar, posso adicionar mais arquivos jar do aplicativo usando as 3 opções principais ao mesmo tempo:

Você pode seguramente assumir isso apenas no modo Cliente, não no modo de Cluster. Como eu já disse anteriormente. Além disso, o exemplo que você deu tem alguns argumentos redundantes. Por exemplo, passar JARs para --driver-library-path é inútil, você precisa passá-los para extraClassPath se quiser que eles estejam em seu classpath. 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 

Outra abordagem na spark 2.1.0 é usar --conf spark.driver.userClassPathFirst=true durante o spark-submit, que altera a prioridade da carga de dependência e, portanto, o comportamento da ignição, dando prioridade aos flasks do usuário está adicionando ao caminho de class com a opção --jars .

Há restrição ao uso de –jars se você deseja especificar um diretório para a localização do arquivo jar / xml que não permite expansões de diretório. Isso significa que você precisa especificar o caminho absoluto para cada jarro. Se você especificar –driver-class-path e estiver executando na class do driver do modo de cluster de fios, não será atualizado. Podemos verificar se o caminho de class é atualizado ou não sob o faísca ou o servidor do histórico da faísca sob o ambiente da aba. Opção que funcionou para mim para passar flasks que contêm expansões de diretório e que trabalhavam no modo de cluster de fios era a opção –conf. É melhor passar os caminhos de class do driver e do executor como – conf, que os adiciona ao próprio object de session e esses caminhos são refletidos na Configuração do Spark. Mas por favor, certifique-se de colocar flasks no mesmo caminho no cluster.

 spark-submit --master yarn --queue spark_queue --deploy-mode cluster --num-executors 12 --executor-memory 4g --driver-memory 8g --executor-colors 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