E aí, pessoal! Boas-vindas a Alura. O instrutor Vinicius Dias vai te guiar nesse curso sobre System Design, arquitetura de sistemas e escalabilidade de aplicações PHP.
Audiodescrição: Vinicius Dias é um homem branco de olhos castanhos. Tem cabelo curto e escuro, usa bigode e cavanhaque e está com uma camisa cinza com as mangas pretas. Ao fundo, uma parede branca sem decorações.
Se você é uma pessoa que trabalha com desenvolvimento há algum tempo ou já tem alguma experiência na área de desenvolvimento, esse curso é para você!
Vamos aprender a criar aplicações escaláveis, isto é, que aguentam uma demanda crescente. Por exemplo, se for uma aplicação web, vai aguentar muitas requisições.
Nesse curso, vamos começar com uma aplicação de arquitetura mais simples e comum. Aos poucos, vamos evoluir e adicionar novos componentes a arquitetura dessa aplicação.
Por isso, vamos falar muito sobre system design ou arquitetura de sistemas. São termos sinônimos que abrangem as decisões que tomamos em relação ao que envolve a nossa aplicação.
Por exemplo, vamos entender a arquitetura inicial da aplicação com a qual vamos trabalhar por meio de um diagrama. Nesse curso, não vamos ter o front-end, só a parte da API.
Vamos ter uma pessoa usuária acessando a nossa aplicação, a API recebe os acessos diretamente e lê e escreve dados um banco de dados relacional. Além disso, a API também tem acesso a um sistema externo de um servidor de e-mail.
Repara que é uma aplicação monolítica. É assim que vamos começar o curso. Também vamos terminar o curso com uma aplicação monolítica, mas o diagrama da arquitetura vai ser bem diferente.
No segundo diagrama, a pessoa usuária novamente acessa a aplicação. Porém, as chamadas para a API vão passar por um load balancer (balanceamento de carga). Com isso, podemos ter vários servidores de API.
Além disso, vamos ter o conceito de message broker (fila de mensageria). Para ler os dados dessa fila, vamos ter outro processo que chamamos de queue worker (trabalhador de fila). Dessa forma, a API e o processo que lida com as mensagens vão estar separados.
Além do banco de dados relacional que vamos acessar para ler e escrever os dados, também vamos ter um banco de dados em memória, por exemplo, para armazenar cache.
Por fim, vamos ter um serviço de armazenamento. Vamos conversar sobre a possibilidade de ter um serviço de externo para armazenamento de arquivo para armazenar relatórios que teremos na aplicação.
Perceba como o primeiro diagrama é bem simples e com poucos componentes, enquanto o segundo diagrama é bem mais completo e escalável.
Para você aproveitar melhor esse curso, é importante que você tenha conhecimentos sólidos sobre Docker.
Como temos vários componentes nessa arquitetura (como load balancer, servidor da API, banco de dados relacional e em memória), vamos disponibilizá-los através do Docker Compose. Assim, cada pedaço da arquitetura vai ser um contêiner diferente.
Existem cursos na Alura específicos sobre Docker. É importante que você os faça antes de continuar nesse curso.
Sobre linguagens de programação e framework, esse curso é de PHP. Porém, não tem problema ser uma pessoa desenvolvedora de outra linguagem, como C# ou Java.
Boa parte do que vamos aprender nesse curso é genérico e relacionado a system design e arquitetura de sistemas. Por isso, não importa qual a linguagem de programação você conhece. Mas, é preciso que você tenha um bom domínio dos conceitos de desenvolvimento web.
Agora, vamos falar especificamente sobre PHP. Para você entender sobre o que vamos abordar, é interessante que você tenha feito os cursos de Laravel ou Symfony. Lá, vamos ter aprendido boa parte dos conceitos que vamos aplicar sobre uma nova perspectiva nesse curso.
Se você não completou os cursos sobre os frameworks Laravel e Symfony, saiba que não são obrigatórios, mas vão te ajudar bastante a acompanhar o que faremos. Contudo, você pode fazer esse curso primeiro para entender sobre a escalabilidade de uma aplicação e depois estudar detalhes específicos dos frameworks.
Além desses cursos, recomendamos outros conteúdos para incrementar seu aprendizado:
Já temos cursos específicos na Alura sobre cada parte da nossa aplicação para você se aprofundar na ferramenta.
A ideia desse curso é você focar no aprendizado de escalabilidade de aplicações, conceitos de arquitetura de sistemas e system design.
Se você ficar com alguma dúvida, te convidamos a fazer parte do servidor do Discord da Alura. Lá, você pode levantar questionamentos e ajudar outras pessoas que possam estar estudando o mesmo tema. Também te convidamos a participar do fórum da Alura, onde você pode postar e responder dúvidas de outras pessoas.
Esperamos que tirem muito proveito desse conteúdo. No próximo vídeo, vamos conhecer a aplicação na qual vamos trabalhar durante esse curso.
Agora que você já tem o sistema rodando e a aplicação funcionando, vamos te explicar o que é essa aplicação.
A ideia dessa aplicação é ser uma API para um consultório médico que permite cadastrar especialistas e avaliações (reviews) para cada especialista.
Na atividade "Preparando o ambiente", disponibilizamos os passos para preencher o banco de dados com essas informações. Dessa forma, já temos muitos dados nessa aplicação inicial.
O endereço dessa API é:
http://localhost:8123/api
Nesse endereço, você vai acessar todos os endpoints. Dentre eles, os endpoints principais que teremos acesso são:
/specialists
: para acessar a lista de especialistas;/reviews
: para acessar as avaliações;/login
: para trabalahar com a autenticação.A aplicação está em inglês, porque é uma língua comum no dia a dia de uma pessoa desenvolvedora.
Vamos tentar acessar http://localhost:8123/api/specialists
para recuperar a lista de especialistas. Faremos isso utilizando o Postman, mas você pode utilizar qualquer cliente HTTP.
Após apertar o botão "Send" (ou atalho "Ctrl + Enter"), tentamos realizar essa requisição GET
e recebemos o status 401
na resposta, informando que não estamos autorizados a fazer essa requisição.
{
"message": "Unauthenticated."
}
No corpo da resposta, temos um JSON com a chave message
e o valor Unauthenticated
, ou seja, não autenticado. Isso significa que ainda não fizemos o login.
Para corrigir esse problema, vamos acessar http://localhost:8123/api/login
também com o Postman, mas utilizando o verbo POST
.
No corpo da requisição, vamos passar um JSON contendo o e-mail e senha de uma pessoa usuária foi criada automaticamente para você:
{
"email": "email@example.com",
"password": "12345678"
}
OK
Quando enviamos essa requisição, recebemos um status 200 OK
e no corpo da resposta também recebemos um "OK".
Agora, estamos logados. Com isso, uma sessão foi armazenada no Postman e, portanto, podemos realizar a requisição GET
do endoint /specialists
.
Trecho da resposta:
{
"current_page": 1,
"data": [
{
"id": "99438af9-8f33-4b97-bd34-d677cbd70854",
"created_at": "2023-05-27T02:15:34.000000Z",
"updated_at":"2023-05-27T02:15:34.000000Z",
"crm": "37.855.dg",
"name": "Thaddeus Koepp",
"specialty": "ortopedia",
"email": "kuhic.jamar@example.org"
},
Desse modo, conseguimos visualizar a lista de especialistas. Repare que a lista já está paginada. Na página 1, temos os dados de ID, data de criação e atualização, CRM do especialista, nome, especialidade e o e-mail.
Cada objeto vai ter todas essas chaves do array do JSON e seus respectivos valores.
],
"first_page_url": "http://localhost:8123/api/specialists?page=1",
"from": 1,
"last_page": 67,
"last_page_url": "http://localhost:8123/api/specialists?page=67",
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost:8123/api/specialists?page=1",
"label": "1",
"active": true
},
No final do JSON, temos os detalhes de paginação. Temos a URL para a primeira página, para a última página, para a próxima página, para a quantidade de páginas, etc.
Nessa lista de especialistas, vamos pegar um especialista qualquer e copiar seu ID, por exemplo, o segundo especialista. Agora, vamos fazer uma nova requisição para buscar duas avaliações.
Vamos acessar http://localhost:8123/api/specialists/
seguido do ID copiado e /reviews
.
http://localhost:8123/api/specialists/99438b05-4575-4644-a38b-04dadb69afcd/reviews
Após fazer uma requisição de tipo GET
para esse endereço, temos a lista de avaliações para esse segundo especialista.
Trecho da resposta:
{
"current_page": 1,
"data": [
{
"id": "99438b05-52ca-4761-9337-63299b898280",
"created_at": "2023-05-27T02:15:42.000000Z",
"updated_at": "2023-05-27T02:15:42.000000Z",
"specialist_id": "99438b05-4575-4644-a38b-04dadb69afcd",
"rating": 5,
"comment": "Veritatis nostrum quam in eius saepe totam."
},
Novamente, temos o ID, data de criação e atualização, ID do especialista, nota da avaliação de 1 a 10 e um comentário em texto.
No contexto do nosso sistema, temos uma lista de especialistas e lista de avaliações.
Para você entender melhor, vamos analisar um pequeno diagrama que explica o contexto da nossa aplicação.
A pessoa usuária vai acessar esse avaliador, que é o sistema de avaliação de médicos. Nesse sistema, vamos usar um servidor de e-mail para notificar a pessoa especialista que ela recebeu uma nova avaliação.
Vamos acessar o Postman para criar uma nova avaliação, usando o mesmo endereço com o ID do especialista que copiamos anteriormente. Porém, vamos fazer uma requisição do tipo POST
.
http://localhost:8123/api/specialists/99438b05-4575-4644-a38b-04dadb69afcd/reviews
Passaremos o conteúdo como um JSON, tendo uma chave rating
com uma nota 8
. Também passaremos uma chave comment
, tendo um valor como string de um comentário da avaliação em português.
{
"rating": ,
"comment": "Comentário da avaliação em português"
}
Ao clicar em "Send" para realizar o cadastro dessa avaliação, temos um status 201 Created
, informando que a avaliação foi criada.
{
"specialist_id": "99438b05-4575-4644-a38b-04dadb69afcd",
"rating": 8,
"comment": "Comentário da avaliação em português",
"id": "99913c0c-3901-4bcd-9d59-e5565a94ee8e",
"updated_at": "2023-07-04T17:09:27.000000Z",
"created_at": "2023-07-04T17:09:27.000000Z"
}
Quando acessamos o endereço localhost:8025
no navegador, temos acesso a uma aplicação de e-mail chamada Mailpit. Essa aplicação que já fornecemos junto com o sistema inicial vai interceptar todos os e-mails que foram enviados para a aplicação.
No inbox, já temos acesso ao e-mail da nova avaliação, enviado para o e-mail do especialista ygerlach@example.net
:
You have a new Review
Rating: 8
Comment: Comentário da avaliação em português
Em inglês, nos é informado que temos uma nova avaliação com a nota e o comentário. Assim, conseguimos avaliar o conteúdo desse e-mail.
Essa é a nossa aplicação. Repare que temos o sistema avaliador e temos um sistema externo que utilizamos para enviar e-mails e notificar a pessoa especialista que recebeu uma nova avaliação.
Agora que entendemos o contexto, vamos efetivamente conhecer problemas desse sistema, falar sobre sua arquitetura e aumentar sua escalabilidade no próximo vídeo.
Já entendemos como é a API onde vamos trabalhar. Recapitulando o diagrama mostrado anteriormente, temos a figura de uma pessoa usuária que acessa o sistema avaliador que usa o servidor de e-mail. Por exemplo, podemos utilizar o protocolo SMTP para enviar esses e-mails.
Agora que entendemos o contexto, vamos utilizar outro cliente diferente do Postman. É só uma questão de preferência do instrutor, mas você pode continuar a utilizar o Postman.
Vamos abrir o PHP Storm, onde já temos as requisições configuradas. Vamos realizar a requisição do tipo POST
de login para armazenar a sessão e ter a pessoa usuária logada, clicando no botão de play à esquerda da requisição.
### Login
POST http://localhost:8123/api/login
Accept: application/json
Content-Type: application/json
{
"email": "email@example.com",
"password": "12345678"
}
Response code: 200 (OK); 197ms (197 ms); Content length: 2 bytes
Temos a mesma resposta de "OK".
Em seguida, vamos tentar acessar a lista de especialistas.
### All Specialists
GET http://localhost:8123/api/specialists
Accept: application/json
Temos novamente aquela longa resposta que já havíamos visualizado.
Response code: 200 (OK); Time: 84 ms (84 ms); Content length: 5132 bytes
Mas também temos algumas informações como o código da resposta, que foi 200 (OK)
. Nesse computador com suas configurações, o tempo da resposta foi de aproximadamente 84
milissegundos.
E se buscamos as reviews de algum especialista? Vamos pegar o ID do segundo especialista e substituir no endereço para buscar todas as avaliações desse especialista. É a mesma requisição que fizemos no vídeo anterior.
### Specialist's review
GET http://localhost:8123/api/specialists/99438b05-4575-4644-a38b-04dadb69afcd/reviews
Accept: application/json
Response code: 200 (OK); Time: 82 ms (82 ms); Content length: 6168 bytes
Tivemos um tempo de resposta de 82
milissegundos, bastante semelhante ao anterior.
Agora, vamos adicionar outra avaliação para aquele mesmo especialista, assim como fizemos anteriormente. Adicionamos uma nota 9
e o comentário como Nova avaliação
.
### New review for Vinicius
POST http://localhost:8123/api/specialists/99438b05-4575-4644-a38b-04dadb69afcd/reviews
Accept: application/json
Content-Type: application/json
{
"rating" : 9,
"comment": "Nova avaliação"
}
Ao enviar essa requisição, sabemos que vamos salvar essa avaliação no banco de dados e também enviar um e-mail. Repare que isso vai fazer a aplicação demorar mais para responder.
Response code: 201 (Created); Time: 181 ms (181 ms); Content length: 224 bytes
Recebemos o status de sucesso, 201
que informa que foi criado. O tempo que a API levou para devolver foi de 181
milissegundos. Isso é mais do que o dobro do que demorávamos normalmente.
Já sabíamos que salvar uma avaliação no banco de dados demora mais do que buscar uma avaliação no banco de dados. Quando inserimos uma informação em um banco, ele vai precisar verificar a consistência dos dados, atualizar tabela de índices, conferir se todos os checks estão conferidos.
Contudo, mais do que o dobro do tempo é uma demora muito grande.
Mais uma vez, no diagrama da aplicação, temos uma seta do sistema avaliador se comunicando com um sistema externo que é o servidor de e-mail. O envio de e-mail também demora e consome tempo.
Estamos enviando esse e-mail na hora em que adicionamos a avaliação. Será que a pessoa que está adicionando a avaliação precisa esperar que o especialista receba seu e-mail? Não precisa.
Ao invés do avaliador mandar o e-mail na hora, ele poderia salvar uma informação de que tem um e-mail para enviar, já responder à pessoa usuária e só depois fazer esse envio. Em outras palavras, queremos tornar o envio desse e-mail assíncrono.
O que queremos fazer? Queremos pegar a aplicação e adicionar algo para conseguir armazenar tarefas para serem executadas no futuro. No nosso caso, a tarefa é enviar um e-mail. Fazer isso no Laravel é muito simples.
Vamos abrir o projeto no PHP Storm. Dentro da pasta "app > Mail", vamos acessar a classe ReviewCreated.php
.
Nessa classe, após extends Mailable
, vamos implementar o ShouldQueue
. Essa interface diz para o sistema do Laravel que o e-mail não precisa ser enviado na hora. Assim, vai ser armazenado em uma fila que depois vai ser processada.
ReviewCreated.php
:
use Illuminate\Contracts\Queue\ShouldQueue;
class ReviewCreated extends Mailable implements ShouldQueue
{
// código omitido…
}
Antes de continuar, vamos abrir aquele sistema de e-mail Mailpit no navegador. Vamos voltar para a lista de e-mail e apagar todas os e-mails do inbox, clicando em "Delete all" na lateral esquerda.
Agora, vamos refazer a requisição de adicionar uma nova avaliação. Quando enviamos essa requisição novamente, o tempo de resposta já diminuiu. Foi de 181 para 136 milissegundos.
Response code: 201 (Created); Time: 136 ms (136 ms); Content length: 224 bytes
Ainda demora mais do que buscar dados, porque inserir um dado no banco demora mais do que buscar. Isso é esperado.
Além disso, só temos um e-mail enviado em um cenário local, ou seja, na nossa máquina. Em um sistema real, esse servidor de e-mails vai estar em outro computador e até em outra rede em outro continente. Essa demora seria ainda maior.
O simples fato de deixar o envio assíncrono faz com que a resposta seja bem mais rápida.
Porém, ao abrir o sistema de e-mail no navegador, o e-mail não está no inbox. Se você fez os cursos de Laravel ou Symfony, você sabe que falta uma parte crucial do processo: ter um código que vai ler a fila de tarefas onde está armazenado a tarefa de enviar o e-mail.
No cenário do Laravel, vamos abrir um terminal e passar o comando php artisan queue:work
.
No nosso caso, como utilizamos o Docker, queremos rodar esse comando dentro do contêiner app
que contém a nossa aplicação. Portanto, antes de php
, vamos digitar docker compose exec app
.
docker compose exec app php artisan queue:work
Ao executar, está sendo processado a tarefa de envio de e-mail ReviewCreated
:
2023-07-04 17:19:33 App\Mail\ReviewCreated
Feito isso, quando acessamos o sistema de e-mail no navegador, já temos o e-mail informando que uma nova avaliação foi criada.
You have a new Review
Rating: 9
Comment: Nova avaliação
Agora, temos dois processos diferentes. Em um processo, a API recebe e responde às requisições, salva no banco de dados e faz todo a lógica de negócios. Já o outro processo consome as mensagens na fila.
Essa separação nos trouxe algumas vantagens. No próximo vídeo, vamos entender melhor quais são as vantagens, além de ter uma resposta mais rápida.
A seguir, vamos falar sobre conceitos como performance e escalabilidade. Te espero lá!
O curso Arquitetura com PHP: escalando uma aplicação monolítica possui 139 minutos de vídeos, em um total de 45 atividades. Gostou? Conheça nossos outros cursos de PHP 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:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.