Por que você pode precisar emular a infraestrutura de serviços web da Amazon?
Antes de tudo, está economizando - economizando tempo para desenvolvimento e depuração e o que é igualmente importante - economizando dinheiro com o orçamento do projeto. É claro que o emulador não será 100% idêntico ao ambiente original que estamos tentando emular. Mas, com o objetivo de acelerar o desenvolvimento e a automação do processo, as semelhanças existentes devem ser suficientes. A coisa mais atual que aconteceu em 2018 com a AWS foi o bloqueio pelos provedores de IP dos endereços IP das sub-redes da AWS na Federação Russa. E esses bloqueios afetaram nossa infraestrutura localizada na nuvem da Amazônia. Se você planeja usar a tecnologia da AWS e colocar o projeto nessa nuvem, o desenvolvimento e teste de emulação mais do que compensa.

Na publicação, mostrarei como conseguimos realizar esse truque com os serviços S3, SQS, RDS PostgreSQL e Redshift ao migrar um data warehouse existente para a AWS por muitos anos.
Isso é apenas parte da
reunião do meu último ano no
mapa , que corresponde aos temas dos hubs da AWS e Java. A segunda parte diz respeito aos bancos de dados PostgreSQL, Redshift e coluna, e sua versão em texto pode ser publicada nos hubs, vídeos e slides correspondentes, no
site da conferência .
Ao desenvolver um aplicativo para a AWS durante o bloqueio de sub-redes da AWS, a equipe praticamente não os notou no processo diário de desenvolvimento de novas funcionalidades. Os testes também funcionaram e você pode depurar o aplicativo. E somente ao tentar examinar os logs do aplicativo nas logentries, as métricas no SignalFX ou a análise de dados no Redshift / PostgreSQL RDS ficaram desapontadas - os serviços não estavam disponíveis na rede do provedor russo. A emulação da AWS nos ajudou a não perceber isso e evitar atrasos muito maiores ao trabalhar com a nuvem Amazon através de uma rede VPN.
Cada provedor de nuvem “escondido” tem muitos dragões e você não deve ceder à publicidade. Você precisa entender por que tudo isso é necessário para o provedor de serviços. Obviamente, a infraestrutura existente da Amazon, Microsoft e Google tem vantagens. E quando eles dizem que tudo é feito apenas para facilitar o seu desenvolvimento, eles provavelmente tentam colocar você na sua agulha e dar a primeira dose de graça. Para que mais tarde eles não saiam da infraestrutura e da tecnologia específica. Portanto, tentaremos evitar o bloqueio do fornecedor. É claro que nem sempre é possível abstrair completamente de decisões específicas e acho que, muitas vezes, é possível abstrair quase 90% em um projeto. Mas os 10% restantes do projeto, vinculados a um provedor de tecnologias muito importantes, estão otimizando o desempenho do aplicativo ou os recursos exclusivos dos quais não existem em mais nenhum outro lugar. Eles devem sempre lembrar as vantagens e desvantagens das tecnologias e se proteger o máximo possível, não "sentar-se" em uma API específica de um provedor de infraestrutura em nuvem.
A Amazon escreve sobre o
processamento de mensagens em seu site. A essência e a abstração das tecnologias de troca de mensagens são as mesmas em todos os lugares, embora haja nuances - mensagens passando por filas ou tópicos. Portanto, a AWS recomenda o uso do Apache ActiveMQ fornecido e gerenciado para migrar aplicativos de um broker de mensagens existente e para novos aplicativos Amazon SQS / SNS. Este é um exemplo de ligação à sua própria API, em vez da API JMS padronizada e dos protocolos AMQP, MMQT, STOMP. É claro que esse provedor, com sua solução, pode ter um desempenho mais alto, suportar escalabilidade etc. Do meu ponto de vista, se você usar suas bibliotecas, e não APIs padronizadas, haverá muito mais problemas.
A AWS possui um banco de dados Redshift. É um banco de dados distribuído com uma arquitetura paralela massiva. Você pode carregar uma grande quantidade de dados em tabelas em vários sites Redshft na Amazon e executar consultas analíticas em grandes conjuntos de dados. Este não é um sistema OLTP em que é importante executar pequenas solicitações em um pequeno número de registros com freqüência suficiente com garantias ACID. Ao trabalhar com Redshift, supõe-se que você não tenha um grande número de consultas por unidade de tempo, mas elas podem ler agregados em uma quantidade muito grande de dados. Esse sistema é posicionado pelo fornecedor para
atualizar seu data warehouse (armazém) na AWS e prometer um simples carregamento de dados. O que não é de todo verdade.
Um trecho da documentação sobre quais
tipos o Amazon Redshift
suporta . É um conjunto bastante escasso e, se você precisar de algo para armazenar e processar dados que não estão listados aqui, será difícil trabalhar. Por exemplo, um GUID.
Pergunta do salão: "E JSON?"
- JSON pode ser gravado apenas como VARCHAR e há várias funções para trabalhar com JSON.
Comentário da platéia: "O Postgres tem suporte JSON normal."
- Sim, possui suporte para esse tipo de dados e funções. Mas o
Redshift é baseado no PostgreSQL 8.0.2. Havia um projeto ParAccel, se não me engano, essa tecnologia de 2005 é uma bifurcação do postgres que possui um agendador para solicitações distribuídas com base em uma arquitetura paralela em massa. Cinco a seis anos se passaram e esse projeto foi licenciado para a plataforma Amazon Web Servces e recebeu o nome Redshift. Algo foi removido do Postgres original, muito foi adicionado. Eles acrescentaram que, relacionado à autenticação / autorização na AWS, com funções, a segurança na Amazon funciona bem. Mas se você precisar, por exemplo, conectar-se do Redshift a outro banco de dados usando a Fonte de Dados Externos, não encontrará isso. Não há funções para trabalhar com XML, funções para trabalhar com JSON duas vezes e calculadas incorretamente.
Ao desenvolver um aplicativo, tente
não depender de implementações específicas e o código do aplicativo depende apenas de abstrações. Você pode criar essas fachadas e abstrações, mas nesse caso existem muitas bibliotecas prontas - fachadas. Que abstraem o código de implementações específicas, de estruturas específicas.É claro que elas podem não suportar toda a funcionalidade, como um "denominador comum" para tecnologias. É melhor desenvolver software confiando em abstrações para simplificar os testes.
Para emular a AWS, mencionarei duas opções. O primeiro é mais honesto e correto, mas funciona mais devagar. O segundo é sujo e rápido. Vou falar sobre a opção de invasão - estamos tentando criar toda a infraestrutura em um único processo - os testes e a opção de plataforma cruzada funcionarão mais rapidamente com o trabalho no Windows (onde o docker nem sempre consegue ganhar dinheiro com você).
O primeiro método é perfeito se você estiver desenvolvendo no linux / macos e tiver docker, seria melhor usar o
localstack atlassian . É conveniente usar
contêineres de teste para integrar o localstack na JVM.
O que me impediu de usar o lockalstack no docker no projeto foi que o desenvolvimento estava no Windows e ninguém atestou a versão alfa do docker quando este projeto iniciou ... Também é possível que eles não tenham permissão para instalar uma máquina virtual com linux e docker em qualquer empresa que leve a sério. à segurança da informação. Não estou falando de trabalhar em um ambiente seguro em bancos de investimento e banir quase todos os firewalls de tráfego lá.
Vamos considerar opções como emular o armazenamento simples S3. Este não é um sistema de arquivos comum da Amazon, mas um armazenamento de objetos distribuídos. Em que você coloca seus dados como um BLOB, sem a possibilidade de modificação e adição de dados. Existem armazenamentos distribuídos completos similares de outros fabricantes. Por exemplo, o armazenamento de objetos distribuídos Ceph permite que você trabalhe com sua funcionalidade usando o
protocolo REST S3 e o cliente existente com modificações mínimas. Mas esta é uma solução bastante pesada para o desenvolvimento e teste de aplicativos java.
Um projeto mais rápido e adequado é a biblioteca java
s3proxy . Ele emula o protocolo REST S3 e o converte nas chamadas da API
jcloud correspondentes e permite o uso de muitas implementações para leitura e armazenamento reais de dados. Ele pode transmitir chamadas para a API do Google App Engine, API do Microsoft Azure, mas para testes é mais conveniente usar o armazenamento temporário do jcloud na RAM. Também é necessário configurar a versão do protocolo de autenticação AWS S3 e especificar os valores de chave e segredo, também configurar o terminal - a porta e a interface na qual esse Proxy S3 escutará. Portanto, seu código usando o cliente AWS SDK deve ser conectado nos testes ao terminal S3 da AWS, não à região da AWS. Novamente, lembre-se de que o s3proxy não suporta todos os recursos da API do S3, mas todos os nossos cenários de uso são perfeitamente compatíveis! Até o upload de várias partes para arquivos grandes é suportado pelo s3proxy.
O Amazon Simple Queue Service é um serviço de fila. Há um
serviço de fila
elasticmq que é escrito em scala e pode ser apresentado ao seu aplicativo usando o protocolo Amazon SQS. Como não o usei no projeto, darei o código de inicialização, confiando nas informações de seus desenvolvedores.
No projeto, segui o caminho inverso e o código depende das abstrações spring-jms JmsTemplate e JmsListener e as dependências do projeto especificam o driver JMS para SQS com.amazonaws: amazon-sqs-java-messaging-lib. É isso que diz respeito ao código principal do aplicativo.
Nos testes, conectamos o Artemis-jms-server como um servidor JMS incorporado para testes e, no contexto do Spring de teste, em vez do connection factory SQS, usamos o connection factory do Artemis. Artemis é a próxima versão do Apache ActiveMQ, um Middleware Orientado a Mensagens moderno e completo - não apenas uma solução de teste. Talvez passemos a usá-lo no futuro, não apenas em autotestes. Assim, usando abstrações JMS em conjunto com o Spring, simplificamos o código do aplicativo e a capacidade de testá-lo facilmente. Você só precisa adicionar as dependências org.springframework.boot: spring-boot-starter-artemis e org.apache.activemq: artemis-jms-server.
Em alguns testes, o PostgreSQL pode ser emulado substituindo-o pelo
H2Database . Isso funcionará se os testes não forem aceitos e não usarem funções específicas do PG. Ao mesmo tempo, o H2 pode emular um subconjunto do protocolo de conexão PostgreSQL sem suporte para tipos e funções de dados. Em nosso projeto, usamos o Foreing Data Wrapper, para que esse método não funcione para nós.
Você pode executar o PostgreSQL real.
O postgresql-embedded baixa a distribuição real, ou melhor, o archive com arquivos binários para a plataforma com a qual executamos, descompacta. No linux no tempfs na RAM, no windows em% TEMP%, o processo do servidor postgresql é iniciado, define as configurações do servidor e os parâmetros do banco de dados. Devido aos recursos de distribuição de distribuição, versões anteriores à PG 11 não funcionam no Linux. Para mim,
criei uma
biblioteca de wrapper que permite obter montagens binárias do PostgreSQL não apenas de um servidor HTTP, mas também do repositório maven. O que pode ser muito útil ao trabalhar em redes isoladas e criar um servidor de CI sem acesso à Internet. Outra conveniência no trabalho com meu wrapper é a anotação do componente CDI, que facilita o uso do componente no contexto do Spring, por exemplo. A implementação da interface do servidor AutoClosable apareceu mais cedo do que no projeto original. Não é necessário lembrar de parar o servidor, ele será interrompido quando o contexto do Spring for fechado automaticamente.
Na inicialização, você pode criar um banco de dados com base em scripts, complementando o contexto do Spring com as propriedades apropriadas. Agora estamos criando um esquema de banco de dados usando scripts
flyway para migrar o esquema do banco de dados, que são iniciados sempre que o banco de dados é criado em testes.
Para verificar os dados após a execução dos testes, usamos a biblioteca spring-test-dbunit. Nas anotações dos métodos de teste, indicamos com quais uploads comparar o estado do banco de dados. Isso elimina a necessidade de escrever código para trabalhar com o dbunit, você só precisa adicionar o ouvinte da biblioteca ao código de teste. Você pode especificar em qual ordem os dados das tabelas serão excluídos após a conclusão do método de teste, se o contexto do banco de dados for reutilizado entre os testes. Em 2019, existe uma abordagem mais moderna implementada no
piloto de banco de dados que funciona com o junit5. Você pode ver um exemplo de uso, por exemplo
aqui .
O mais difícil foi emular o Amazon Redshift. Há um projeto
redshift-fake-driver, cujo projeto é emular a carga de dados em lote no banco de dados analítico da AWS. No emulador de protocolo jdbc: postgresqlredshift, os comandos COPY, UNLOAD são implementados, todos os outros comandos são delegados ao driver JDBC PostgreSQL comum.
Portanto, os testes não funcionarão da mesma maneira que no Redshift, a operação de atualização, que usa outra tabela como fonte de dados para atualização (a sintaxe difere no Redshift e no PostgreSQL 9+. Também notei uma interpretação diferente da citação de linha nos comandos SQL entre esses bancos de dados.
Devido à arquitetura de um banco de dados Redshift real, as operações de inserção, atualização e exclusão de dados são bastante lentas e "caras" em termos de E / S. É possível inserir dados com desempenho aceitável apenas em "pacotes" grandes e o comando COPY apenas permite fazer o download de dados de um sistema de arquivos S3 distribuído. Este comando no banco de dados suporta vários formatos de dados AVRO, CSV, JSON, Parquet, ORC e TXT. E o projeto emulador se concentra em CSV, TXT, JSON.
Portanto, para emular o Redshift nos testes, será necessário iniciar o banco de dados PostgreSQL conforme descrito anteriormente e iniciar a emulação do repositório S3. Ao criar uma conexão com o postgres, basta adicionar redshift-fake-driver no caminho da classe e especificar a classe do driver jp.ne.opt.redshiftfake.postgres. FakePostgresqlDriver. Depois disso, você pode usar o mesmo caminho para migrar o esquema do banco de dados, e o dbunit já é familiar para comparar dados após a execução dos testes.
Gostaria de saber quantos leitores usam AWS e Redshift em seu trabalho? Escreva nos comentários sobre sua experiência.
Usando apenas projetos de código aberto, a equipe conseguiu acelerar o desenvolvimento no ambiente da AWS, economizar dinheiro com o orçamento do projeto e não impedir que a equipe trabalhasse quando as sub-redes da AWS foram bloqueadas por Roskomnadzor.