Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sschonss/ms-rabbitmq
https://github.com/sschonss/ms-rabbitmq
Last synced: 18 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/sschonss/ms-rabbitmq
- Owner: sschonss
- Created: 2024-06-29T14:45:26.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2024-06-29T14:59:30.000Z (7 months ago)
- Last Synced: 2024-11-13T02:13:35.371Z (3 months ago)
- Language: JavaScript
- Size: 8.79 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Microservices e Mensageria com PHP, NodeJS, RabbitMQ e Docker
O desenvolvimento de microserviços é uma abordagem arquitetural que estrutura uma aplicação como um conjunto de serviços pequenos e independentes, que são executados em seu próprio processo e se comunicam por meio de protocolos leves, como HTTP, WebSockets ou AMQP.
Neste artigo, vamos criar uma aplicação de microserviços com PHP, RabbitMQ e Docker. O RabbitMQ é um software de mensageria que implementa o protocolo AMQP (Advanced Message Queuing Protocol), que é um protocolo de mensagens assíncronas.
## O que é RabbitMQ?
Vamos imaginar o seguinte cenário: você tem um sistema que precisa enviar e-mails para os usuários. Em vez de enviar os e-mails diretamente, você pode enviar uma mensagem para uma fila de mensagens, que será consumida por um serviço que envia os e-mails. Isso é o que o RabbitMQ faz: ele recebe mensagens de produtores e as envia para consumidores.
Dessa forma é possível desacoplar a produção de mensagens do consumo, o que permite escalar cada parte do sistema de forma independente. Além disso, o RabbitMQ garante que as mensagens sejam entregues na ordem correta e que não sejam perdidas.
## Arquitetura da aplicação
Nossa aplicação será composta por dois microserviços: um produtor e um consumidor. O produtor será responsável por enviar mensagens para uma fila de mensagens, e o consumidor será responsável por consumir as mensagens e exibi-las no terminal.
Nosso primeiro passo será criar o arquivo `docker-compose.yml` para definir os serviços da nossa aplicação:
```yaml
services:
rabbitmq:
image: "rabbitmq:3-management"
container_name: "rabbitmq"
ports:
- "15672:15672"
- "5672:5672"php-app:
build: ./php-app
depends_on:
- rabbitmqnode-app:
build: ./node-app
depends_on:
- rabbitmq
```Neste arquivo, definimos três serviços: `rabbitmq`, `php-app` e `node-app`. O serviço `rabbitmq` é baseado na imagem `rabbitmq:3-management`, que inclui a interface de gerenciamento do RabbitMQ. Os serviços `php-app` e `node-app` são baseados em imagens customizadas que iremos criar.
---
### Criando o produtor com PHP
Agora, vamos criar o diretório `php-app` e o arquivo `Dockerfile` dentro dele:
```bash
$ mkdir php-app
$ touch php-app/Dockerfile
```No arquivo `Dockerfile`, vamos definir a imagem base e copiar os arquivos da aplicação:
```Dockerfile
FROM php:7.4-cli
RUN apt-get update && apt-get install -y librabbitmq-dev libssl-dev git unzip wget curlRUN docker-php-ext-install sockets pdo pdo_mysql
RUN pecl install amqp && docker-php-ext-enable amqpCOPY . /usr/src/myapp
WORKDIR /usr/src/myappRUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer clear-cache
RUN composer install
CMD ["php", "./publisher.php"]
```Neste arquivo, definimos a imagem base `php:7.4-cli` e instalamos as dependências necessárias para o RabbitMQ e o Composer. Em seguida, copiamos os arquivos da aplicação para o diretório `/usr/src/myapp`, instalamos as dependências do Composer e executamos o script `publisher.php`.
Agora, vamos criar o arquivo `publisher.php` na raiz do projeto:
```php
channel();
break;
} catch (Exception $e) {
echo "Failed to connect to RabbitMQ. Retrying in $retryDelay seconds...\n";
sleep($retryDelay);
}
}if (!isset($connection)) {
echo "Not possible to connect to RabbitMQ. Exiting...\n The application will be restarted by Docker\n";
exit(1);
}$channel->queue_declare('hello', false, false, false, false);
$msg = new AMQPMessage('Hello, RabbitMQ! Now is ' . date('Y-m-d H:i:s'));
$channel->basic_publish($msg, '', 'hello');echo " [x] Sent 'Hello, RabbitMQ!'\n";
$channel->close();
$connection->close();
```Neste arquivo, criamos uma conexão com o RabbitMQ, declaramos uma fila chamada `hello` e enviamos uma mensagem para essa fila. Em seguida, fechamos a conexão com o RabbitMQ.
Perceba que estamos tentando conectar ao RabbitMQ várias vezes, com um intervalo de 5 segundos entre as tentativas. Isso é importante para garantir que a aplicação consiga se conectar ao RabbitMQ mesmo que ele não esteja disponível imediatamente.
Isso é uma prática comum em aplicações distribuídas, onde a disponibilidade dos serviços pode variar ao longo do tempo, pesquise mais sobre `circuit breaker` e `retry pattern`.
Mas para instalar as dependências do RabbitMQ e do Composer, precisamos criar o arquivo `composer.json` na raiz do projeto:
```json
{
"require": {
"php-amqplib/php-amqplib": "^3.1",
"phpseclib/phpseclib": "^3.0"
}
}
```
---### Criando o consumidor com Node.js
Agora, vamos criar o diretório `node-app` e o arquivo `Dockerfile` dentro dele:
```bash
$ mkdir node-app
$ touch node-app/Dockerfile
```No arquivo `Dockerfile`, vamos definir a imagem base e copiar os arquivos da aplicação:
```Dockerfile
FROM node:14WORKDIR /usr/src/app
COPY package*.json ./
RUN npm installCOPY . .
CMD ["node", "subscriber.js"]
```Neste arquivo, definimos a imagem base `node:14`, copiamos os arquivos da aplicação para o diretório `/usr/src/app`, instalamos as dependências do Node.js e executamos o script `subscriber.js`.
Agora, vamos criar o arquivo `subscriber.js` na raiz do projeto:
```javascript
const amqp = require('amqplib');async function connectWithRetry() {
const maxRetries = 5;
const retryDelay = 5000;for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const connection = await amqp.connect('amqp://rabbitmq');
return connection;
} catch (err) {
console.error(`Not possible to connect to RabbitMQ. Retrying in ${retryDelay}ms. Attempt ${attempt} of ${maxRetries}.`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}throw new Error(`Failed to connect to RabbitMQ after ${maxRetries} attempts`);
}async function receiveMessages() {
try {
const connection = await connectWithRetry();
const channel = await connection.createChannel();const queue = 'hello';
await channel.assertQueue(queue, { durable: false });console.log(" [*] Waiting for messages in %s.", queue);
channel.consume(queue, function(msg) {
console.log(" [x] Received: %s", msg.content.toString());
}, {
noAck: true
});
} catch (err) {
console.error(err.message);
process.exit(1);
}
}receiveMessages();
```Neste arquivo, criamos uma conexão com o RabbitMQ, declaramos uma fila chamada `hello` e consumimos as mensagens dessa fila. Em seguida, exibimos as mensagens no terminal.
Assim como no produtor, estamos tentando conectar ao RabbitMQ várias vezes, com um intervalo de 5 segundos entre as tentativas. Isso é importante para garantir que o consumidor consiga se conectar ao RabbitMQ mesmo que ele não esteja disponível imediatamente.
E para instalar as dependências do RabbitMQ, precisamos criar o arquivo `package.json` na raiz do projeto:
```json
{
"name": "node-app",
"version": "1.0.0",
"description": "",
"main": "subscriber.js",
"dependencies": {
"amqplib": "^0.8.0"
},
"author": "",
"license": "ISC"
}
```---
### Executando a aplicação
Agora que criamos os serviços do RabbitMQ, do produtor e do consumidor, vamos executar a aplicação com o Docker Compose:
```bash
$ docker-compose up --build
```Isso irá criar os containers dos serviços e executar a aplicação. Você verá as mensagens enviadas pelo produtor sendo exibidas no terminal pelo consumidor.
O RabbitMQ também estará disponível na porta 15672, onde você pode acessar a interface de gerenciamento e visualizar as filas e as mensagens.
Com isso, criamos uma aplicação de microserviços com PHP, RabbitMQ e Docker. Essa abordagem arquitetural permite escalar cada parte do sistema de forma independente e garante a entrega das mensagens na ordem correta.
Espero que este artigo tenha sido útil e que você possa aplicar esses conceitos em seus projetos. Se tiver alguma dúvida ou sugestão, deixe nos comentários.
Qualquer dúvida, estou à disposição.
Link do Repositório: [Microservices e Mensageria com PHP, RabbitMQ e Docker](#)