Gerenciar dependências de pipeline no Dataflow

Muitos pipelines do Apache Beam podem ser executados usando os ambientes de execução padrão do Dataflow. No entanto, alguns casos de uso de processamento de dados se beneficiam do uso de mais bibliotecas ou classes. Nesses casos, pode ser necessário gerenciar as dependências do pipeline.

A lista a seguir fornece alguns motivos para você precisar gerenciar as dependências do pipeline:

  • As dependências fornecidas pelo ambiente de execução padrão são suficientes para seu caso de uso.
  • As dependências padrão têm colisões de versão ou têm classes e bibliotecas incompatíveis com o código do pipeline.
  • É necessário fixar em versões específicas da biblioteca para o pipeline.
  • Você tem um pipeline Python que precisa ser executado com um conjunto consistente de dependências.

A maneira como você gerencia as dependências depende do pipeline usar Java, Python ou Go.

Java

Classes e bibliotecas incompatíveis podem causar problemas de dependência do Java. Se o pipeline contém código e configurações específicos do usuário, o código não pode conter versões mistas de bibliotecas.

Problemas de dependência do Java

Quando o pipeline tem problemas de dependência Java, pode ocorrer um dos seguintes erros:

  • NoClassDefFoundError: esse erro ocorre quando uma classe inteira não está disponível durante o tempo de execução.
  • NoSuchMethodError: esse erro ocorre quando a classe no caminho de classe usa uma versão que não contém o método correto ou quando a assinatura do método mudou.
  • NoSuchFieldError: esse erro ocorre quando a classe no caminho de classe usa uma versão que não tem um campo obrigatório durante o tempo de execução.
  • FATAL ERROR: esse erro ocorre quando uma dependência integrada não pode ser carregada corretamente. Ao usar um arquivo JAR uber (sombreado), não inclua bibliotecas que usem assinaturas no mesmo arquivo JAR, como o Conscrypt.

Gerenciamento de dependências

Para simplificar o gerenciamento de dependências para pipelines Java, o Apache Beam usa artefatos de lista de materiais (BoM). A BoM ajuda as ferramentas de gerenciamento de dependências a selecionar combinações de dependências compatíveis. Para mais informações, consulte SDK do Apache Beam para dependências do Java na documentação do Apache Beam.

Para usar uma BoM com o pipeline e adicionar explicitamente outras dependências à lista de dependências, adicione as seguintes informações ao arquivo pom.xml do artefato do SDK. Para importar a BoM das bibliotecas corretas, use beam-sdks-java-io-google-cloud-platform-bom.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.beam</groupId>
      <artifactId>beam-sdks-java-google-cloud-platform-bom</artifactId>
      <version>LATEST</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-sdks-java-core</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-runners-google-cloud-dataflow-java</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.beam</groupId>
    <artifactId>beam-sdks-java-io-google-cloud-platform</artifactId>
  </dependency>
</dependencies>

O artefato beam-sdks-java-core contém somente o SDK principal. É preciso adicionar explicitamente outras dependências à lista de dependências, como E/S e executores.

Python

Quando você executa jobs do Dataflow usando o SDK do Apache Beam para Python, o gerenciamento de dependências é útil nos seguintes cenários:

  • O pipeline usa pacotes públicos do índice de pacotes do Python (PiPy, na sigla em inglês), e você quer disponibilizar esses pacotes remotamente.
  • Você quer criar um ambiente reproduzível.
  • Para reduzir o tempo de inicialização, evite a instalação de dependências nos workers no momento da execução.

Definir dependências de pipeline do Python

É possível usar um único script ou notebook Python para escrever um pipeline do Apache Beam, mas no ecossistema Python geralmente o software é distribuído como pacotes. Para facilitar a manutenção do pipeline, quando o código do pipeline incluir vários arquivos, agrupe os arquivos do pipeline como um pacote do Python.

  • Defina as dependências do pipeline no arquivo setup.py do pacote.
  • Prepare o pacote para os workers usando a opção de pipeline --setup_file.

Quando os workers remotos são iniciados, eles instalam seu pacote. Para ver um exemplo, consulte juliaset no GitHub do Apache Beam.

Para estruturar o pipeline como um pacote do Python, siga estas etapas:

  1. Crie um arquivo setup.py para o projeto. No arquivo setup.py, inclua o argumento install_requires para especificar o conjunto mínimo de dependências do pipeline. O exemplo a seguir mostra um arquivo setup.py básico.

    import setuptools
    
    setuptools.setup(
      name='PACKAGE_NAME',
      version='PACKAGE_VERSION',
      install_requires=[],
      packages=setuptools.find_packages(),
    )
    
  2. Adicione o arquivo setup.py, o arquivo de fluxo de trabalho principal e um diretório com o restante dos arquivos para o diretório raiz do projeto. Esse agrupamento de arquivos é o pacote do Python para o pipeline. A estrutura do arquivo é semelhante ao exemplo a seguir:

    root_dir/
      package_name/
        my_pipeline_launcher.py
        my_custom_transforms.py
        ...other files...
      setup.py
      main.py
    
  3. Para executar o pipeline, instale o pacote no ambiente de envio. Use a opção de pipeline --setup_file para organizar o pacote para os workers. Exemplo:

    python -m pip install -e .
    python main.py --runner DataflowRunner --setup_file ./setup.py  <...other options...>
    

Essas etapas simplificam a manutenção do código do pipeline, especialmente quando o código aumenta em tamanho e complexidade. Para outras maneiras de especificar dependências, consulte Como gerenciar dependências de pipeline do Python na documentação do Apache Beam.

Usar contêineres personalizados para controlar o ambiente de execução

Para executar um pipeline com o SDK do Apache Beam para Python, os workers do Dataflow precisam de um ambiente Python que contenha um intérprete, o SDK do Apache Beam e as dependências do pipeline. As imagens de contêiner do Docker fornecem o ambiente adequado para executar o código do pipeline.

Imagens de contêiner de banco de imagens são lançadas com cada versão do SDK do Apache Beam e essas imagens incluem as dependências do SDK do Apache Beam. Para mais informações, consulte dependências do SDK do Apache Beam para Python na documentação do Apache Beam.

Quando o pipeline requer uma dependência que não está incluída na imagem de contêiner padrão, a dependência precisa ser instalada no ambiente de execução. A instalação de pacotes no ambiente de execução pode ter as seguintes consequências:

  • O tempo de inicialização do worker aumenta devido à resolução, ao download e à instalação da dependência.
  • O pipeline requer uma conexão com a Internet para ser executado.
  • Não determinismo ocorre devido a versões de software em dependências.

Para evitar esses problemas, forneça o ambiente de execução em uma imagem de contêiner do Docker personalizada. Usar uma imagem de contêiner personalizada do Docker que tenha as dependências do pipeline pré-instaladas tem os seguintes benefícios:

  • Garante que o ambiente de execução do pipeline tenha o mesmo conjunto de dependências sempre que você iniciar o job do Dataflow.
  • Permite controlar o ambiente de execução do pipeline.
  • Evita a resolução de dependências demorada na inicialização.

Ao usar imagens de contêiner personalizadas, considere as seguintes orientações:

  • Evite usar a tag :latest com suas imagens personalizadas. Marque seus builds com uma data, versão ou um identificador exclusivo. Essa etapa permite reverter para uma configuração de trabalho conhecida, se necessário.
  • Use um ambiente de lançamento compatível com a imagem do contêiner. Para mais orientações sobre como usar contêineres personalizados, consulte Criar uma imagem de contêiner.

Para detalhes sobre como pré-instalar dependências do Python, consulte Pré-instalar dependências do Python.

Controlar o ambiente de inicialização com os modelos do Dataflow

Se o pipeline exigir outras dependências, talvez seja necessário instalá-las no ambiente de execução e no de inicialização. O ambiente de inicialização executa a versão de produção do pipeline. Como o ambiente de inicialização precisa ser compatível com o de execução, use as mesmas versões de dependências nos dois ambientes.

Para ter um ambiente de lançamento em contêiner e reproduzível, use os modelos Flex do Dataflow. Para mais informações, consulte Criar e executar um modelo Flex. Ao usar modelos Flex, considere os seguintes fatores:

Essa construção torna seu ambiente de lançamento reproduzível e compatível com seu ambiente de execução.

Para conferir um exemplo que segue essa abordagem, consulte o tutorial Modelo Flex de um pipeline com dependências e um contêiner personalizado (em inglês) no GitHub.

Para mais informações, consulte Tornar o ambiente de inicialização compatível com o ambiente de execução e Controlar as dependências que o pipeline usa na documentação do Apache Beam.

Go

Quando você executa jobs do Dataflow usando o SDK do Apache Beam para Go, os módulos Go são usados para gerenciar dependências. O arquivo a seguir contém as dependências padrão de compilação e ambiente de execução usadas pelo pipeline:

https://raw.githubusercontent.com/apache/beam/vVERSION_NUMBER/sdks/go.sum

Substitua VERSION_NUMBER pela versão do SDK que você está usando.

Para informações sobre como gerenciar dependências para o pipeline do Go, consulte Como gerenciar dependências na documentação do Go.