Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Arquitetura Java: crie uma infraestrutura escalável

Arquitetura Java: crie uma infraestrutura escalável

Infraestrutura com Docker - Apresentação

Olá, boas-vindas a mais um curso focado em Arquitetura Java aqui na Alura. Meu nome é Rodrigo Caneppele, sou um dos instrutores da Escola de Programação e vou acompanhar vocês ao longo desse terceiro curso dessa formação.

Audiodescrição: Rodrigo é um homem de pele branca, cabelo curto e castanho. Está usando um suéter cinza. Ele está em um dos estúdios da Alura, e o ambiente é iluminado por uma luz azul. À sua frente, um microfone com espuma protetora. Ao fundo, uma parede lisa e uma estante com alguns itens decorativos à direita.

O que vamos aprender?

Nos cursos anteriores dessa formação, exploramos bastante a parte de arquitetura mais voltada para o design de código, utilizando alguns padrões como Domain-Driven Design, Clean Architecture e pensando em como organizar o código para deixar o domínio da aplicação isolado das tecnologias.

Agora, neste terceiro curso, o foco será na parte de Infraestrutura. Vamos procurar responder:

Para isso, vamos aprender, principalmente, como focar e projetar uma infraestrutura utilizando a linguagem Java.

Você provavelmente já desenvolveu aplicações Java, possivelmente utilizando o Spring, que é o principal framework para desenvolvimento de APIs Rest, aplicações, seja monólito ou com microserviços em Java. Mas, como projetar a infraestrutura para colocar essa aplicação no ar?

Nesse curso, vamos discutir sobre como pegar uma máquina num servidor de produção, seja ela na nuvem ou numa rede privada dentro da empresa, e como fazer o deploy dessa aplicação.

Então, vamos aprender como fazer o build de um projeto com Java, utilizando o Maven, e como fazer para colocar essa aplicação no ar, fazendo o deploy dentro de um servidor.

Para isso, vamos utilizar containers Docker. O Docker facilita muito nosso trabalho para garantir uma portabilidade. Não precisaremos nos preocupar com instalação de Java na versão X, do Maven ou de qualquer biblioteca. Tudo isso será feito de uma maneira mais simplificada, utilizando containers Docker.

Então, no curso, vamos utilizar o Docker como ferramenta para criar o container, tanto da aplicação quanto das dependências dessa aplicação - como banco de dados, servidor de cache, servidor de proxy reverso, dentre outras tecnologias.

Vamos precisar, obviamente, gerenciar esses containers. Para facilitar o trabalho, vamos utilizar o Docker Compose, um plugin do Docker para gerenciar múltiplos containers.

Ao invés de ficarmos subindo cada um dos containers de maneira isolada, gerenciando-os manualmente, vamos usar o Docker Compose para simplificar esse trabalho.

Além disso, vamos aprender a utilizar o Nginx como servidor de proxy reverso. Ou seja, as requisições não vão cair diretamente na nossa API. Elas vão bater no Nginx e ele vai atuar como um proxy reverso, encaminhando a requisição para a nossa aplicação, rodando dentro do servidor com o Docker.

E também, depois que a aplicação já estiver no ar, rodando e funcionando, vamos discutir bastante sobre otimizações. Se a aplicação estiver com problemas de performance, apresentando lentidão, como fazemos para otimizar visando melhorar a performance da aplicação?

O grande foco do curso será na camada de persistência, no acesso ao banco de dados, porque geralmente é ali que fica o principal ponto de gargalo em uma aplicação.

Toda vez que ela precisa acessar o banco de dados, milhões de problemas podem acontecer e eles impactam na performance. Vamos discutir sobre algumas estratégias para otimizar o acesso ao banco de dados.

Por fim, vamos focar na parte de escalabilidade e disponibilidade. E se a nossa API cair no servidor, tendo uma sobrecarga devido a um pico de acessos, como fazemos para ter uma melhor escalabilidade e disponibilidade? Se uma instância cair, podemos ter várias outras instâncias para responder as requisições.

Vamos aprender a projetar uma infraestrutura focada em elasticidade, usando também o Nginx para fazer o balanceamento de carga, melhorando, então, a disponibilidade e a escalabilidade - e, consequentemente, a performance da nossa aplicação.

Pré-requisitos

Para acompanhar o curso com tranquilidade, é desejável que você tenha conhecimentos de Java e de APIs Rest desenvolvidas com o Spring Boot, pois nosso projeto é uma API Rest utilizando o Spring Boot.

Não é o foco desse curso aprender a desenvolver uma API Rest, pois temos outros cursos e formações na Alura com esse intuito. Vamos apenas pegar uma API Rest em Java com o Spring Boot e utilizá-la para fazer esse deploy e conhecer e aprender a usar todos esses recursos.

Além disso, é importante que você também já tenha conhecimentos no Docker e no Docker Compose. O foco do curso não é ensinar Docker nem Docker Compose, pois vamos apenas utilizar essas tecnologias para facilitar o nosso aprendizado e o desenvolvimento do nosso projeto de infraestrutura na nuvem. Aqui na Alura, também temos diversos cursos e formações focados especialmente no Docker.

Além disso, vamos usar o Nginx como ferramenta de servidor web atuando como proxy reverso. Então, também é importante que você já conheça essa ferramenta. Também há cursos na Alura voltados para Nginx.

Geralmente um servidor de produção utiliza Linux, e o nosso servidor vai utilizar Linux. Então é importante que você conheça como funciona esse sistema operacional, seu terminal, como rodar seus comandos e como fazer acesso via SSH a um servidor remoto.

Vamos utilizar bastante o terminal para rodar comandos dentro da nossa máquina que está hospedada em um servidor Linux. Também há cursos na Alura focados nisso aqui na Alura.

Recados iniciais

Ao longo do curso, se tiver alguma dúvida ou dificuldade, não hesite em postar no fórum da plataforma ou na nossa comunidade do Discord.

Ao final do curso, lembre-se de deixar a sua avaliação, pois isso é muito importante para melhorarmos sempre os nossos conteúdos.

Tudo pronto? Então, nos encontramos na primeira aula! Até lá!

Infraestrutura com Docker - Build do projeto

Vamos começar o nosso curso! Nesta primeira aula, o foco será na parte de deploy (implantação), que é o processo de colocar a aplicação no ar.

Até então, sempre trabalhamos localmente, no próprio computador, utilizando uma IDE, desenvolvendo e testando no navegador com uma ferramenta de testes de API. No entanto, a ideia é colocar essa aplicação em um servidor. Para isso, precisamos entender como esse processo funciona.

Vamos usar o mesmo projeto dos cursos anteriores, do CodeChella API, mas com algumas modificações. Ele está disponibilizado para download na atividade de preparação de ambiente desta aula.

Feito o download do arquivo ZIP, vamos importá-lo no IntelliJ. Esse projeto tem diversas funcionalidades e já queremos colocá-lo no ar, mesmo que ainda não esteja 100% pronto, para entender como fazemos para acessar essa aplicação rodando fora do computador local.

Build pelo Maven

Até então, sempre executamos o projeto pelo IntelliJ, rodando a classe com o método main. Mas, no servidor, não teremos o IntelliJ executando. Precisamos, de alguma forma, gerar o executável da aplicação. No caso, como a aplicação utiliza Maven, vamos gerar esse executável utilizando o Maven.

Uma das maneiras de fazer isso é pela própria IDE. No IntelliJ, no canto superior direito da tela, temos uma aba do Maven. Clicando nela, temos uma pasta do nosso projeto. Podemos expandi-la e, dentro de "Lifecycle", há alguns comandos do Maven que podemos selecionar e executar.

No caso, queremos executar o comando package, que é o comando para empacotar a nossa aplicação num arquivo JAR. Vamos clicar nesse comando com o botão direito e selecionar a opção "Run Maven Build".

Com isso, o terminal será aberto e vai disparar o processo do Maven: compilar as classes do projeto, compilar e executar os testes automatizados, caso existam, e gerar o empacotamento do nosso projeto.

Finalizado o processo, recebemos a mensagem "BUILD SUCCESS". Então, ele gerou o pacote da nossa aplicação, o arquivo executável que vamos utilizar para fazer o deploy em um servidor.

E onde fica esse arquivo? Por padrão, em uma aplicação utilizando o Maven, esse arquivo fica no diretório raiz do projeto, numa pasta chamada "target". É nela onde ele coloca os arquivos gerados pelo Maven.

Se expandirmos essa pasta "target", notaremos vários arquivos usados para fazer a compilação. O que interessa para nós é o arquivo .jar. Como se trata de uma aplicação Java utilizando Spring Boot, ele vai gerar um arquivo .jar, e esse é o nosso executável, que servirá para rodar a aplicação no servidor.

Esse processo que acabamos de executar é chamado de build. Toda vez que fazemos o deploy da aplicação, primeiro temos que fazer o processo de build. Dependendo da linguagem de programação e das tecnologias usadas no projeto, esse processo pode mudar. No caso do Java com Maven, como vimos, o próprio Maven faz esse processo para nós, gerando o arquivo .jar.

Agora, podemos copiar esse arquivo .jar, de alguma forma, para o servidor onde faremos o deploy. Lá, vamos ter que rodar alguns comandos para executar essa aplicação.

Nesse primeiro vídeo, o objetivo era mostrar como fazer esse processo de build. Utilizamoa o IntelliJ, que tem a integração com o Maven. Mas, caso você esteja usando outra IDE, ou não queira fazer isso pela IDE, tem outras formas de fazer o build também. Uma delas é pelo próprio terminal.

Build pelo terminal

Vamos abrir o terminal da IDE no diretório raiz do projeto.

Toda aplicação Spring Boot criada pelo site http://start.spring.io tem o projeto gerado com a estrutura do Maven, com alguns arquivos adicionais. Por exemplo, os arquivos mvnw (para executar no Linux e MacOS) e mvnw.cmd (para Windows) são scripts do Maven que você pode utilizar via linha de comando.

Para fazer o build rodando esses scripts, rodamos o seguinte comando no terminal:

./mvnw package

É uma forma um pouco mais complicada que fazer diretamente pela IDE, mas funciona igualmente, executando a build com sucesso.

Em um servidor onde não teremos tela, não teremos IDE ou interface gráfica, podemos executar esses scripts via terminal!

No próximo vídeo continuamos o nosso processo. Feito o build, vamos aprender a fazer o deploy!

Infraestrutura com Docker - Adicionando Docker no projeto

Já aprendemos a fazer o build do nosso projeto, que no caso de uma aplicação Java, utilizando o Spring Boot, nada mais é do que gerar o arquivo .jar. Aprendemos a fazer isso pelo IntelliJ e também pela linha de comando.

Ou seja, agora temos o arquivo executável que representa a nossa aplicação. Basta rodarmos esse executável no servidor, seja qual for a plataforma que vamos usar, cloud (nuvem) ou não.

Conseguimos simular a forma de executar essa aplicação no servidor diretamente no terminal da IDE. Vamos rodar o comando java -jar, para rodar uma aplicação baseada no arquivo .jar, seguido do caminho do arquivo. No caso do instrutor, está na pasta target o arquivo nomeado codechella-api-1.0.jar.

java -jar target/codechella-api-1.0.jar

O comando acima é o que vamos executar no servidor para rodar a nossa aplicação.

Se executarmos esse comando no terminal, ele vai executar da mesma forma que executaríamos pelo IntelliJ, rodando a nossa classe com o método main.

Mas, aqui há um ponto importante. Executamos a aplicação pelo terminal e funcionou, ela inicializou e está rodando na porta 8080, ou seja, já podemos disparar as requisições para a API.

Porém, se simplesmente pegarmos um servidor Linux, copiarmos esse .jar e rodarmos esse comando, provavelmente dará um erro, porque não terá o Java instalado. O instrutor tem o Java instalado no nosso computador, por isso funcionou.

Ou seja, não basta ter apenas um servidor puro, só com o sistema operacional instalado, que geralmente é Linux, mas poderia ser o Windows também. Precisamos ter o servidor e configurá-lo para a aplicação: instalar o Java e também as dependências da aplicação. No caso, essa aplicação está usando o banco de dados MySQL, por exemplo, então precisamos ter o MySQL instalado. Precisamos ter todas as configurações no servidor!

Se um dia quisermos trocar de servidor, vamos ter que lembrar de instalar o sistema operacional, instalar o Java na versão específica, instalar o banco de dados na versão específica, instalar o comando X, Y, Z - e tudo isso seria um processo manual, o que pode gerar problemas de portabilidade.

Para resolver isso, temos a tecnologia do Docker. Podemos apenas configurar o Docker no projeto e ele cuidará de toda a infraestrutura e as dependências da aplicação. Vamos fazer isso!

O objetivo desse curso não é ensinar Docker, tanto que conhecê-lo é pré-requisito para esse curso - se necessário, confira os nossos cursos focados em Docker desde os fundamentos.

Configurando o Docker no projeto

No nosso projeto, não temos o Docker instalado e configurado. Então, esse será o passo realizado nesse vídeo.

No diretório raiz da aplicação, vamos criar o arquivo Dockerfile, onde vamos ensinar para o Docker a receita para criar o sistema operacional e o nosso container contendo a aplicação.

Para isso, clicamos com o botão direito na raiz do projeto no Explorador de arquivos e, depois, selecionar "New > File". Vamos nomear o arquivo como Dockerfile, com a letra "D" em maiúsculo, sem extensão.

Agora precisamos ensinar para o Docker os passos a serem seguidos ao criar o container do nosso projeto, indicando a versão do Linux, do Java, os arquivos, etc. Vamos configurar tudo com o seguinte código:

Dockerfile

FROM eclipse-temurin:17-jdk-alpine as builder
WORKDIR application
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw package -DskipTests
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract


FROM eclipse-temurin:17-jre-alpine
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

Acima estão as configurações do nosso arquivo Dockerfile.

Ele está dividido em duas etapas. Na primeira, que chamamos de builder, fazemos o build da aplicação utilizando o Maven. Então, nem vamos precisar mais executar aquele build manual como mostramos no vídeo anterior, pois isso será executado pelo próprio Docker.

Nessa parte, estamos basicamente falando para o Docker: o Java na versão 17, crie um diretório para a aplicação chamado application, copie os arquivos do projeto, copie o executável (mvn) copie o .xml, faça o ./mvnw package e gere o arquivo .jar da aplicação.

No segundo passo, na parte inferior, indicamos para o Docker como rodar a aplicação.

Há várias maneiras de executar uma aplicação Java com Spring Boot via Docker. A que vamos utilizar é apenas uma das abordagens que vamos usar no curso. Nela, ele "descompacta" o arquivo .jar e traz as dependências do Spring.

Com isso já ensinamos para o Docker: quando você for criar uma imagem da nossa aplicação, essa é a "receita de bolo" para, quando você gerar um container, você construir a aplicação - gere o build e depois execute a aplicação da forma indicada. Isso foi ensinado em mais detalhes nos cursos de Docker da Alura!

Criando uma imagem da aplicação

Criado o Dockerfile, vamos pedir para o Docker criar uma imagem da aplicação. Para fazer isso, precisamos ter o Docker instalado na máquina.

Vamos abrir o terminal, parar o projeto que estava rodando com o atalho "Ctrl + C", limpar o terminal com "Ctrl + L" e escrever o comando docker build. Vamos pedir para ele criar uma imagem, então temos que dar um apelido com o comando -t para dizer qual é a tag. Vamos chamar de alura/codchella e colocar na versão 1.0:

docker build -t alura/codechella:1.0 .

Com o comando acima, estamos falando para o Docker: crie uma imagem do nosso projeto, com essa tag, no diretório local (por isso o ponto final), que é o diretório raiz da aplicação.

Ao pressionar "Enter" para executar, ele vai ler o Dockerfile com a receita para construir a imagem conforme configuramos.

O Dockerfile varia conforme a linguagem e as tecnologias que você estiver utilizando no projeto.

Como podemos conferir na linha 1 do arquivo, falamos para ele usar como base a imagem jdk17-alpine. Se não tivermos essa imagem no nosso computador, ele vai baixar da internet, então isso pode demorar um pouco.

Ao finalizar esse processamento, o Docker criou uma imagem!

Vamos limpar o terminal com "Ctrl + L" e rodar o seguinte comando para listar as imagens que temos do Docker do nosso computador:

docker image list

No retorno, temos a imagem alura/codechella na versão 1.0, inclusive com o ID da imagem.

Agora podemos criar um container baseado nessa imagem. Basta rodarmos o comando:

docker run alura/codechella:1.0

Com isso, ele vai criar um container baseado naquela imagem e vai subir a nossa aplicação com Spring Boot.

Perceba aquele problema que previmos: deu um erro no terminal. Notaremos a exceção registrada diz que foi relacionada com acesso ao banco de dados. Ou seja, ele tentou acessar o MySQL, mas aconteceu aquele problema que mencionamos.

Quando executamos a aplicação sem o Docker, localmente no nosso computador, tudo funciona, porque já temos o Java instalado na versão certa e o MySQL, que é o banco de dados. Mas, dentro do container, temos que configurar tudo.

Se observarmos o nosso Dockerfile, aqui estamos configurando apenas a aplicação. No primeiro passo apenas geramos o build da aplicação usando uma máquina Linux que tem o JDK 17; e no segundo passo falamos que também queremos uma máquina com o Java 17 e que queremos rodar a aplicação Java.

É parecido com aquele java -jar, mas, e o banco de dados? Não ensinamos para o Docker onde está o banco de dados. Ele vai tentar se conectar com o banco de dados local, não vai achar e vai dar erro. Então, no próximo vídeo vamos aprender como lidar com essas dependências da aplicação.

Sobre o curso Arquitetura Java: crie uma infraestrutura escalável

O curso Arquitetura Java: crie uma infraestrutura escalável possui 140 minutos de vídeos, em um total de 56 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas