Perguntas e respostas sobre Apache Spark em entrevista (5/9)

Perguntas e respostas sobre Apache Spark em entrevista (5/9)

O próximo grupo de perguntas, é sobre Gerenciamento e Deploy.

Seguindo o raciocínio, selecionei 3 perguntas dentre as mais recorrentes. Respondi da forma como aprendi e validei por meio de minhas experiências com Spark.  

Quais são os modos de deployment do Spark?

O Spark pode ser implantado de diversos modos. Como vamos escolher qual vai ser o melhor, vai depender da infraestrutura e da necessidade de cada projeto.

O que vou descrever a seguir não é uma regra cravada em pedra, é o modo que eu uso. Gosto de deixar isso claro, pois tenho amigos que utilizam os modos de deploy para finalidades diferente. Não há certo e errado, apenas o que atende a cada fim.

  • Para MVP e testes locais, eu uso Local Mode. Aqui, executamos o Spark em um único nó, e um processo JVM.
  • Quando preciso de pequenos clusters dedicados, uso Standalone Mode, por ser simples de configurar e usar. Esse é o gerenciador de cluster nativo do Spark.
  • Quando preciso compartilhar um cluster entre diferentes frameworks, já dou preferência para o Mesos. É um gerenciador de cluster que pode coordenar e alocar recursos de multiplos frameworks distribuídos.
  • Quando entro para um projeto onde o Hadoop já está em uso, então opto pelo Yarn, pois ele permite que o Spark e outras aplicações Hadoop compartilhem os mesmos recursos de cluster.
  • Em ambientes de Cloud e container, onde precisamos de escalabilidade automática e orquestração, utilizo o Kubernetes. O Spark pode ser executado utilizando os pods e os serviços Kubernetes.    

Sabe configurar alocação de recursos no Spark?

Sim. Fazer esses ajustes de alocação de recursos é importante para garantir o desempenho e utilizar os recursos do cluster da melhor forma possível.

Algumas configurações básicas são:

  1. Número de Executores: [spark.executor.instances] Define o número de executores que serão lançados para a aplicação. Exemplo: spark-submit --num-executors 10.
  2. Memória dos Executores: [spark.executor.memory] Define a quantidade de memória alocada para cada executor. Exemplo: spark-submit --executor-memory 4G.
  3. Número de Núcleos por Executor: [spark.executor.cores] Define o número de núcleos (threads) que cada executor usará. Exemplo: spark-submit --executor-cores 4.
  4. Memória do Driver: [spark.driver.memory] Define a quantidade de memória alocada para o driver. Exemplo: spark-submit --driver-memory 2G.
  5. Número de Núcleos do Driver: [spark.driver.cores] Define o número de núcleos alocados para o driver (relevante em alguns modos de deployment, como YARN).

Algumas configurações mais avançadas:

  1. spark.dynamicAllocation.enabled: Permite que o Spark ajuste automaticamente o número de executores durante a execução da aplicação. Exemplo: spark-submit --conf spark.dynamicAllocation.enabled=true.
  2. spark.dynamicAllocation.minExecutors e spark.dynamicAllocation.maxExecutors: Define os limites mínimo e máximo de executores quando o gerenciamento dinâmico de recursos está habilitado.
  3. spark.sql.shuffle.partitions: Define o número de partições para operações de shuffle no Spark SQL. Ajustar esse valor pode melhorar o desempenho de operações que envolvem shuffling de dados.
  4. spark.locality.wait: Define o tempo que o Spark espera para uma execução local antes de tentar uma execução em um local remoto. Isso pode afetar a eficiência da utilização de dados locais.
  5. spark.executor.extraJavaOptions: Pode ser usado para passar parâmetros de JVM para ajustar o comportamento de garbage collection. Exemplo: spark.executor.extraJavaOptions="-XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=35".

Exemplo de Submissão de Trabalho

sh

 spark-submit \
  --class <main_class> \
  --master <cluster_mode> \
  --deploy-mode <deploy_mode> \
  --num-executors 10 \
  --executor-memory 4G \
  --executor-cores 4 \
  --driver-memory 2G \
  --conf spark.dynamicAllocation.enabled=true \
  --conf spark.dynamicAllocation.minExecutors=5 \
  --conf spark.dynamicAllocation.maxExecutors=20 \
  <application_jar> \
  <application_args>        

Ao ajustar a alocação de recursos, é importante balancear entre a quantidade de executores, a memória e os núcleos disponíveis no cluster para evitar sobrecarregar um nó específico.

Utilizar ferramentas como o Spark UI, logs de aplicação e métricas do cluster para monitorar o desempenho e fazer ajustes conforme necessário. Então, realizar testes com diferentes configurações para encontrar o ponto ótimo para a aplicação.

Como você monitora e depura jobs no Spark?

Monitorar e debuggar jobs no Spark é parte natural do trabalho para garantir que as aplicações estejam executando corretamente. Eu faço isso utilizando ferramentas de monitoramento como Spark UI; visualizo a execução de jobs no histórico de aplicações do Spark; monitoro os clusteres com YARN ResourceManager, Meses Web UI ou Kubernetes Dashboard.

Também faço uso dos Logs de Aplicação, como: Driver Logs e Executor Logs, que são os logs que podem ser visualizados no console onde a aplicação foi iniciada, ou onde configuramos o sistema de gerenciamento.

Ferramentas como JvisualVM e YourKit também podem ser usadas para inspecionar o comportamento da JVM e detectar gargalos de desempenho.

Algumas das boas práticas que aprendi com colegas de trabalho, incluem:

  • OutOfMemoryError: Ajustar a memória dos executores e do driver conforme necessário.
  • Skewed Data: Identificar partições desbalanceadas que podem causar lentidão.
  • Serialization Issues: Garantir que os objetos usados em operações RDD são serializáveis.
  • Persistência de Dados: Usar o cache/persist para evitar recalcular RDDs.
  • Reparticionamento: Reparticionar conjuntos de dados grandes para evitar operações de shuffle excessivas.
  • Integrar sistemas de monitoramento como Grafana para visualização contínua de métricas.

Entre para ver ou adicionar um comentário

Outros artigos de Renan Lima Andrade

Outras pessoas também visualizaram

Conferir tópicos