The Codest
  • Sobre nós
  • Serviços
    • Desenvolvimento de software
      • Desenvolvimento de front-end
      • Desenvolvimento backend
    • Staff Augmentation
      • Programadores Frontend
      • Programadores de back-end
      • Engenheiros de dados
      • Engenheiros de nuvem
      • Engenheiros de GQ
      • Outros
    • Aconselhamento
      • Auditoria e consultoria
  • Indústrias
    • Fintech e Banca
    • E-commerce
    • Adtech
    • Tecnologia da saúde
    • Fabrico
    • Logística
    • Automóvel
    • IOT
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • A nossa equipa
  • Case Studies
  • Saber como
    • Blogue
    • Encontros
    • Webinars
    • Recursos
Carreiras Entrar em contacto
  • Sobre nós
  • Serviços
    • Desenvolvimento de software
      • Desenvolvimento de front-end
      • Desenvolvimento backend
    • Staff Augmentation
      • Programadores Frontend
      • Programadores de back-end
      • Engenheiros de dados
      • Engenheiros de nuvem
      • Engenheiros de GQ
      • Outros
    • Aconselhamento
      • Auditoria e consultoria
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • A nossa equipa
  • Case Studies
  • Saber como
    • Blogue
    • Encontros
    • Webinars
    • Recursos
Carreiras Entrar em contacto
Seta para trás VOLTAR
2022-06-28
Desenvolvimento de software

Symfony: Comunicação de microsserviços - parte I

The Codest

Sebastian Luczak

PHP Chefe de unidade

Leia a primeira parte da nossa série PHP dedicada à comunicação de microsserviços na estrutura Symfony e a forma mais popular - comunicação AMQP usando RabbitMQ.

A arquitetura moderna das aplicações obrigou os programadores a mudar a forma de pensar sobre a comunicação entre os diferentes componentes dos sistemas de TI. Antigamente, a questão era mais simples - a maioria dos sistemas era criada como estruturas monolíticas ligadas entre si por uma rede de ligações de lógica empresarial. A manutenção dessas dependências numa PHP projeto foi um enorme desafio para Desenvolvedores PHPe a crescente popularidade do SaaS e o enorme aumento da popularidade das nuvem serviços causou que hoje em dia se ouça cada vez mais falar de microsserviços e a modularidade das aplicações.

Como é que, ao criar microsserviços independentes, podemos fazê-los trocar informações entre si?

Este artigo é o primeiro de uma série de publicações sobre comunicação de microsserviços em Symfony e abrange a forma mais popular - a comunicação AMQP utilizando o RabbitMQ.

Objetivo

Criar duas aplicações independentes e conseguir a comunicação entre elas utilizando apenas o barramento de mensagens.

O conceito

Temos duas aplicações imaginárias e independentes:
* app1que envia notificações por correio eletrónico e SMS aos empregados
* app2O sistema de gestão do trabalho: permite-lhe gerir o trabalho dos empregados e atribuir-lhes tarefas.

Pretendemos criar um sistema moderno e simples através do qual a atribuição de trabalho a um empregado em app2 enviará uma notificação ao cliente utilizando app1. Apesar das aparências, isto é muito simples!

Preparação

Para efeitos deste artigo, utilizaremos o Symfony mais recente (versão 6.1 no momento da redação) e a versão mais recente do PHP (8.1). Em alguns passos muito simples, criaremos um site local funcional Docker com dois microsserviços. Tudo o que precisa é de:
* um computador funcional,
* Docker + instalado Ambiente do Docker Compose
* e um CLI do Symfony e algum tempo livre.

Ambiente de tempo de execução

Usaremos os recursos do Docker como uma ferramenta de virtualização de aplicativos e de contêineres. Vamos começar criando uma árvore de diretórios, uma estrutura para dois Aplicações Symfonye descrever a infraestrutura dos nossos ambientes utilizando o docker-compose.yml ficheiro.

 cd ~
 mkdir microservices-in-symfony
 cd microservices-in-symfony
 symfony nova app1
 symfony nova app2
 toque em docker-compose.yml

Criámos dois diretórios para duas aplicações Symfony separadas e criámos um diretório docker-compose.yml para iniciar o nosso ambiente.

Vamos adicionar as seguintes secções ao ficheiro docker-compose.yml file:

versão: "3.8

serviços:
app1:
nome de utilizador: app1
compilação: app1/.
restart: on-failure
ficheiro env: app1/.env
ambiente:
APPNAME: app1
tty: true
stdinopen: true

app2:
nome de utilizador: app2
construir: app2/.
restart: on-failure
ficheiro env: app2/.env
ambiente:
APPNAME: app2
tty: true
stdinopen: true

rabbitmq:
nome de utilizador: rabbitmq
imagem: rabbitmq:management
portas:
- 15672:15672
- 5672:5672
ambiente:
- RABBITMQDEFAULTUSER=utilizador
- RABBITMQDEFAULT_PASS=senha

Fonte código disponível diretamente: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml

Mas espere, o que aconteceu aqui? Para quem não está familiarizado com o Docker, o ficheiro de configuração acima pode parecer enigmático, no entanto o seu objetivo é muito simples. Usando o Docker Compose, estamos construindo três "serviços":

  • app1: que é um contentor para a primeira aplicação Symfony
  • app2: que é o contentor para a segunda aplicação Symfony
  • rabbitmq: a imagem da aplicação RabbitMQ como uma camada de middleware de comunicação

Para um funcionamento correto, continuamos a precisar de Dockerfile que são a fonte para construir as imagens. Portanto, vamos criá-los:

 touch app1/Dockerfile
 toque em app2/Dockerfile

Ambos os ficheiros têm exatamente a mesma estrutura e têm o seguinte aspeto:

DE php:8.1

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPIAR . /app/
WORKDIR /app/

ADICIONAR https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions && sync &&
install-php-extensions amqp

EXECUTAR apt-get update
&& apt-get install -y libzip-dev wget --no-install-recommends
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

EXECUTAR docker-php-ext-install zip;

CMD bash -c "cd /app && composer install && php -a"

Código fonte disponível diretamente: /thecodest-co/microservices-in-symfony/blob/main/app1/Dockerfile

O ficheiro acima é utilizado pelo Docker Compose para construir um contentor a partir de uma imagem PHP 8.1 com o Composer e a extensão AMQP instalada. Além disso, ele executa o intepretador PHP no modo append para manter o contêiner em execução em segundo plano.

O seu diretório e árvore de ficheiros devem agora ter o seguinte aspeto:

 .
 ├── app1
 │ └── Dockerfile
 | (...) # Estrutura do aplicativo Symfony
 ├─── app2
 │ └── Dockerfile
 | (...) # Estrutura do aplicativo Symfony
 └── docker-compose.yml

O primeiro microserviço Symfony

Vamos começar com o app1 e a primeira aplicação.
No nosso exemplo, é uma aplicação que ouve e consome mensagens da fila enviadas por app2 como descrito nos requisitos:

atribuição de um trabalho a um trabalhador em app2 enviará uma notificação ao cliente

Vamos começar por adicionar as bibliotecas necessárias. O AMQP é suportado nativamente para o symfony/messenger extensão. Adicionalmente, instalaremos monólogo/monólogo para manter o registo dos registos do sistema para facilitar a análise do comportamento das aplicações.

 cd app1/
 symfony composer req amqp ampq-messenger monolog

Após a instalação, foi adicionado um ficheiro adicional em config/packages/messenger.yaml. É um ficheiro de configuração para o componente Symfony Messenger e não precisamos do seu configuração completa.
Substitua-o pelo ficheiro YAML abaixo:

quadro:
messenger:
# Descomente isto (e o transporte falhado abaixo) para enviar mensagens falhadas para este transporte para tratamento posterior.
# failure_transport: failed

    transportes:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        external_messages:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
            opções:
                auto_setup: false
                exchange:
                    nome: mensagens
                    tipo: direct
                    default_publish_routing_key: from_external
                queues:
                    messages:
                        binding_keys: [from_external]

Código fonte disponível diretamente: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml

O Symfony Messenger é utilizado para comunicação síncrona e assíncrona em aplicações Symfony. Ele suporta uma variedade de transportesou fontes de verdade da camada de transporte. No nosso exemplo, utilizamos a extensão AMQP que suporta o sistema de filas de eventos RabbitMQ.

A configuração acima define um novo transporte chamado mensagens_externas, que faz referência ao MESSENGER_TRANSPORT_DSN e define a escuta direta no mensagens no barramento de mensagens. Nesta altura, edite também o app1/.env e adicionar o endereço de transporte adequado.

"`env

(...)
MESSENGERTRANSPORTDSN=amqp://user:password@rabbitmq:5672//messages
(...)
"
Depois de preparar a estrutura da aplicação e de configurar as bibliotecas, é altura de implementar a lógica comercial. Sabemos que a nossa aplicação deve responder à atribuição de um trabalho a um trabalhador. Também sabemos que a atribuição de um trabalho noapp2system altera o estado do trabalho. Portanto, vamos criar um modelo que imita a alteração de status e salvá-lo no caminhoapp1/Message/StatusUpdate.php`:
imagem
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status;
}

}

Código fonte disponível diretamente: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php

Ainda precisamos de uma classe que implemente a lógica comercial quando o nosso microserviço receber o evento acima da fila. Então, vamos criar uma classe Manipulador de mensagens no app1/Handler/StatusUpdateHandler.php caminho:

imagem
 use PsrLogLoggerInterface;
utilizar SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
protected LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus();

    $this->logger->warning('APP1: {STATUS_UPDATE} - '.$statusDescription);

    // o resto da lógica de negócio, ou seja, enviar o email ao utilizador
    // $this->emailService->email()
}

}

Código fonte disponível diretamente: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php

PHP tornam as coisas muito mais fáceis e significam que, neste caso específico, não temos de nos preocupar com a ligação automática ou a declaração de serviço. O nosso microsserviço para tratar eventos de domínio está pronto, é altura de passar à segunda aplicação.

Segundo microsserviço Symfony

Vamos dar uma vista de olhos no app2 e o segundo diretório Aplicação Symfony. A nossa ideia é enviar uma mensagem para a fila quando um trabalhador recebe uma tarefa no sistema. Então, vamos fazer uma configuração rápida do AMQP e fazer com que nosso segundo microsserviço comece a publicar StatusUpdate eventos para o barramento de mensagens.

A instalação das bibliotecas é exatamente igual à da primeira aplicação.

 cd ..
 cd app2/
 symfony composer req amqp ampq-messenger monolog

Vamos certificar-nos de que o app2/.env contém uma entrada DSN válida para o RabbitMQ:

(...)
 MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq:5672//messages
 (...)

Tudo o que resta é configurar o Symfony Messenger na pasta app2/config/packages/messenger.yaml file:

quadro:
messenger:
# Descomente isto (e o transporte falhado abaixo) para enviar mensagens falhadas para este transporte para tratamento posterior.
# failure_transport: failed

    transportes:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        async:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'

    routing:
        # Encaminhar as mensagens para os transportes
        'AppMessageStatusUpdate': assíncrono

Como se pode ver, desta vez a definição de transporte aponta diretamente para assíncrono e define o encaminhamento sob a forma de envio do nosso StatusUpdate mensagem para o DSN configurado. Esta é a única área de configuração, faltando apenas criar a camada lógica e de implementação da fila AMQP. Para isso, vamos criar o gêmeo StatusUpdateHandler e StatusUpdate aulas em app2.

imagem
 use PsrLogLoggerInterface;
utilizar SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
private readonly LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus();

    $this->logger->warning('APP2: {STATUS_UPDATE} - '.$statusDescription);

    ## lógica comercial, ou seja, envio de notificação interna ou colocação em fila de espera de outros sistemas
}

}
imagem
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status;
}

}


Código fonte disponível diretamente: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php

Por fim, basta criar uma forma de enviar uma mensagem para o barramento de mensagens. Vamos criar um simples Comando Symfony para isso:

imagem
use SymfonyComponentConsoleAttributeAsCommand;
use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;;
use SymfonyComponentMessengerMessageBusInterface;

[AsCommand(

nome: "app:send"

)]
class SendStatusCommand extends Command
{
public function construct(private readonly MessageBusInterface $messageBus, string $name = null)
{
parent::construct($name);
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $status = "Trabalhador X atribuído a Y";

    $this->messageBus->dispatch(
        mensagem: new StatusUpdate($status)
    );

    return Command::SUCCESS;
}

}

Agradecimentos a Injeção de dependência podemos utilizar uma instância de Interface de barramento de mensagens no nosso Command e enviar um StatusUpdate mensagem através do despacho() para a nossa fila. Além disso, também utilizamos aqui os atributos PHP.

É isso - tudo o que resta é executar nosso ambiente Docker Compose e ver como nossos aplicativos se comportam.

Executar o ambiente e testar

Com o Docker Compose, os contentores com as nossas duas aplicações serão construídos e executados como instâncias separadas, a única camada de middleware será o rabbitmq e a nossa implementação do barramento de mensagens.

A partir do diretório raiz do projeto, vamos executar os seguintes comandos:

cd ../ # certifique-se de que está no diretório principal
 docker-compose up --build -d

Esse comando pode levar algum tempo, pois ele constrói dois containers separados com o PHP 8.1 + AMQP e puxa a imagem do RabbitMQ. Seja paciente. Depois que as imagens são construídas, você pode disparar nosso comando a partir de app2 e enviar algumas mensagens para uma fila.

 docker exec -it app2 php bin/console app:send

Podes fazê-lo tantas vezes quantas as que conseguires. Desde que não haja consumidor as suas mensagens não serão processadas. Assim que abrir o app1 e consumir todas as mensagens que lhe forem apresentadas no ecrã.

docker exec -it app1 php bin/console messenger:consume -vv external_messages
imagem

A versão completa código fonte juntamente com o README pode ser encontrado no nosso repositório público The Codest Github

Resumo

O Symfony, com as suas bibliotecas e ferramentas, permite uma abordagem rápida e eficiente ao desenvolvimento de aplicações web. Com alguns comandos e algumas linhas de código, é possível criar um sistema de comunicação moderno entre aplicações. O Symfony, assim como o PHPé ideal para desenvolvimento de aplicações web e graças ao seu ecossistema e facilidade de implementação, este ecossistema atinge alguns dos melhores indicadores de tempo de colocação no mercado.

No entanto, rápido nem sempre significa bom - no exemplo acima, apresentámos a forma mais simples e rápida de comunicação. O que os mais curiosos certamente notarão é a falta de desconexão dos eventos de domínio fora da camada de aplicação - na versão atual, eles são duplicados e não há suporte completo para Envelopeentre outros, não existe Selos. Para estes e outros, convido-o a ler a Parte II, onde abordaremos o tema da unificação da estrutura de domínio das aplicações Symfony num ambiente de microsserviços, e discutiremos o segundo método popular de comunicação de microsserviços - desta vez síncrono, baseado na API REST.

faixa de cooperação

Artigos relacionados

Desenvolvimento de software

PHP 8.2: O que há de novo?

A nova versão do PHP está quase a chegar. Quais são as novas implementações que deve conhecer? Consulte este artigo para ficar a saber!

The Codest
Sebastian Luczak PHP Chefe de unidade
Desenvolvimento de software

Desenvolvimento PHP. Componente de Consola Symfony - Dicas e Truques

Este artigo foi criado com o objetivo de lhe mostrar as dicas e truques mais úteis e recuperáveis sobre o Symfony Console Development.

The Codest
Sebastian Luczak PHP Chefe de unidade

Subscreva a nossa base de conhecimentos e mantenha-se atualizado sobre os conhecimentos do sector das TI.

    Sobre nós

    The Codest - Empresa internacional de desenvolvimento de software com centros tecnológicos na Polónia.

    Reino Unido - Sede

    • Office 303B, 182-184 High Street North E6 2JA
      Londres, Inglaterra

    Polónia - Pólos tecnológicos locais

    • Parque de escritórios Fabryczna, Aleja
      Pokoju 18, 31-564 Cracóvia
    • Embaixada do Cérebro, Konstruktorska
      11, 02-673 Varsóvia, Polónia

      The Codest

    • Início
    • Sobre nós
    • Serviços
    • Case Studies
    • Saber como
    • Carreiras
    • Dicionário

      Serviços

    • Aconselhamento
    • Desenvolvimento de software
    • Desenvolvimento backend
    • Desenvolvimento de front-end
    • Staff Augmentation
    • Programadores de back-end
    • Engenheiros de nuvem
    • Engenheiros de dados
    • Outros
    • Engenheiros de GQ

      Recursos

    • Factos e mitos sobre a cooperação com um parceiro externo de desenvolvimento de software
    • Dos EUA para a Europa: Porque é que as empresas americanas decidem mudar-se para a Europa?
    • Comparação dos centros de desenvolvimento da Tech Offshore: Tech Offshore Europa (Polónia), ASEAN (Filipinas), Eurásia (Turquia)
    • Quais são os principais desafios dos CTOs e dos CIOs?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Direitos de autor © 2026 por The Codest. Todos os direitos reservados.

    pt_PTPortuguese
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese es_ESSpanish nl_NLDutch etEstonian elGreek cs_CZCzech pt_PTPortuguese