PHP 8.2: Mitä uutta?
Uusi versio PHP:stä on aivan nurkan takana. Mitkä ovat ne uudet toteutukset, joista sinun tulisi tietää? Tutustu tähän artikkeliin ja ota selvää!
Lue ensimmäinen osa PHP-sarjastamme, joka on omistettu mikropalveluiden viestinnälle Symfony-kehyksessä ja suosituimmalle tavalle - AMQP-viestinnälle RabbitMQ:n avulla.
Nykyaikainen sovellusarkkitehtuuri on pakottanut kehittäjät muuttamaan ajattelutapaansa tietojärjestelmien eri osien välisestä viestinnästä. Aikoinaan asia oli yksinkertaisempi - useimmat järjestelmät luotiin monoliittisina rakenteina, jotka oli yhdistetty toisiinsa liiketoimintalogiikan yhteyksien verkostolla. Tällaisten riippuvuuksien ylläpitäminen PHP projekti oli valtava haaste PHP-kehittäjätja SaaS-ratkaisujen kasvava suosio sekä SaaS-ratkaisujen suosion valtava kasvu ja pilvi palvelut aiheuttivat sen, että nykyään kuulemme yhä enemmän mikropalveluista ja sovellusten modulaarisuudesta.
Miten voimme luoda itsenäisiä mikropalveluja ja saada ne vaihtamaan tietoja keskenään?
Tämä artikkeli on ensimmäinen sarjassa, jonka aiheena on mikropalvelujen viestintä Symfonyssä ja se kattaa suosituimman tavan - AMQP-viestinnän RabbitMQ:n avulla.
Kahden itsenäisen sovelluksen luominen ja niiden välisen viestinnän toteuttaminen käyttämällä vain Message Bus -väylää.
Meillä on kaksi kuvitteellista, toisistaan riippumatonta sovellusta:
* app1
: joka lähettää työntekijöille sähköposti- ja tekstiviesti-ilmoituksia.
* app2
: jonka avulla voit hallita työntekijöiden työtä ja antaa heille tehtäviä.
Haluamme luoda nykyaikaisen ja yksinkertaisen järjestelmän, jonka avulla työtehtävien jakaminen työntekijälle on mahdollista app2
lähettää asiakkaalle ilmoituksen käyttämällä app1
. Ulkonäöstä huolimatta tämä on hyvin yksinkertaista!
Tässä artikkelissa käytämme uusinta Symfonya (versio 6.1 kirjoitushetkellä) ja uusinta versiota PHP:stä (8.1). Muutamalla hyvin yksinkertaisella askeleella luomme toimivan paikallisen Docker-ympäristön, jossa on kaksi mikropalvelua. Kaikki mitä tarvitset on:
* toimiva tietokone,
* asennettu Docker + Docker Compose -ympäristö
* ja paikallisesti määritetty Symfony CLI ja vapaa-aikaa.
Käytämme Dockerin ominaisuuksia sovellusten virtualisointi- ja konttityökaluna. Aloitetaan luomalla hakemistopuu, puitteet kahdelle Symfony-sovellukset, ja kuvaamme ympäristömme infrastruktuurin käyttämällä apuna mallia docker-compose.yml
tiedosto.
cd ~
mkdir microservices-in-symfony
cd microservices-in-symfony
symfony new app1
symfony new app2
touch docker-compose.yml
Olemme luoneet kaksi hakemistoa kahdelle erilliselle Symfony-sovellukselle ja luoneet tyhjän hakemiston nimellä docker-compose.yml
tiedosto käynnistää ympäristömme.
Lisätään seuraavat osiot docker-compose.yml
file:
versio: '3.8'
palvelut:
app1:
app1
build: app1/.
restart: on-failure
envfile: app1/.env
ympäristö:
APPNAME: app1
tty: true
stdinopen: true
app2:
containername: app2
build: app2/.
restart: on-failure
envfile: app2/.env
ympäristö:
APPNAME: app2
tty: true
stdinopen: true
rabbitmq:
containername: rabbitmq
kuva: rabbitmq:management
portit:
- 15672:15672
- 5672:5672
ympäristö:
- RABBITMQDEFAULTUSER=user
- RABBITMQDEFAULT_PASS=salasana
Lähde koodi saatavilla suoraan: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml
Mutta odota, mitä tässä tapahtui? Dockeria tuntemattomille yllä oleva konfigurointitiedosto saattaa vaikuttaa arvoitukselliselta, mutta sen tarkoitus on hyvin yksinkertainen. Rakennamme Docker Composen avulla kolme "palvelua":
Asianmukaista toimintaa varten tarvitsemme edelleen Dockerfile
tiedostot, jotka ovat lähde kuvien rakentamiseen. Luodaan siis ne:
touch app1/Dockerfile
touch app2/Dockerfile
Molemmilla tiedostoilla on täsmälleen sama rakenne, ja ne näyttävät seuraavilta:
FROM php:8.1
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer /usr/local/bin/composer
COPY . /app/
WORKDIR /app/
ADD 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
RUN apt-get update
&& apt-get install -y libzip-dev wget --no-install-rescommends
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Suorita docker-php-ext-install zip;
CMD bash -c "cd /app && composer install && php -a"
Lähdekoodi saatavilla suoraan: /thecodest-co/microservices-in-symfony/blob/blob/main/app1/Dockerfile
Docker Compose käyttää yllä olevaa tiedostoa rakentaakseen kontin PHP 8.1 -kuvasta, johon on asennettu Composer ja AMQP-laajennus. Lisäksi se ajaa PHP-interpreterin append-tilassa, jotta kontti pysyy käynnissä taustalla.
Hakemisto- ja tiedostopuusi pitäisi nyt näyttää seuraavalta:
.
├── app1
│ └── Dockerfile
| (...) # Symfony-sovelluksen rakenne
├── app2
│ └── Dockerfile
| (...) # Symfony-sovelluksen rakenne
└── docker-compose.yml
Aloitetaan app1
hakemistoon ja ensimmäiseen sovellukseen.
Esimerkissämme se on sovellus, joka kuuntelee ja kuluttaa viestejä jonosta, jonka lähettää app2
vaatimusten mukaisesti:
työn osoittaminen työntekijälle
app2
lähettää ilmoituksen asiakkaalle
Aloitetaan lisäämällä tarvittavat kirjastot. AMQP on natiivisti tuettu symfony/messenger
jatko. Asennamme lisäksi monologi/monologi
seurata järjestelmälokeja sovellusten käyttäytymisen analysoinnin helpottamiseksi.
cd app1/
symfony composer req amqp ampq-messenger monolog
Asennuksen jälkeen lisättiin ylimääräinen tiedosto osoitteeseen config/packages/messenger.yaml
. Se on Symfony Messenger -komponentin konfigurointitiedosto, emmekä tarvitse sen sisältöä. täydellinen kokoonpano.
Korvaa se alla olevalla YAML-tiedostolla:
puitteet:
Messenger:
# Ota tämä (ja alla oleva epäonnistunut kuljetus) kommentti pois, jos haluat lähettää epäonnistuneet viestit tähän kuljetukseen myöhempää käsittelyä varten.
# failure_transport: epäonnistunut
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
external_messages:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'.
options:
auto_setup: false
exchange:
name: messages
type: direct
default_publish_routing_key: from_external
jonot:
messages:
binding_keys: [from_external]
Lähdekoodi saatavilla suoraan: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml
Symfony Messengeriä käytetään synkroniseen ja asynkroniseen viestintään Symfony-sovelluksissa. Se tukee erilaisia kuljetukset, tai siirtokerroksen totuuden lähteet. Esimerkissämme käytämme AMQP-laajennusta, joka tukee RabbitMQ-tapahtumajonojärjestelmää.
Yllä oleva konfiguraatio määrittelee uuden kuljetuksen nimeltä external_messages
, jossa viitataan MESSENGER_TRANSPORT_DSN
ympäristömuuttuja ja määrittelee suoran kuuntelun viestit
kanava viestiväylällä. Muokkaa tässä vaiheessa myös app1/.env
tiedostoon ja lisää asianmukainen kuljetusosoite.
“`env
(…)
MESSENGERTRANSPORTDSN=amqp://user:password@rabbitmq:5672/%2f/messages
(…)
“
After preparing the application framework and configuring the libraries, it is time to implement the business logic. We know that our application must respond to the assignment of a job to a worker. We also know that assigning a job in theapp2system changes the status of the job. So let's create a model that mimics the status change and save it in theapp1/Message/StatusUpdate.php` path:
{
public function __construct(protected string $status){}
public function getStatus(): string
{
return $this->status;
}
}
Lähdekoodi saatavilla suoraan: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php
Tarvitsemme vielä luokan, joka toteuttaa liiketoimintalogiikan, kun mikropalvelumme vastaanottaa edellä mainitun tapahtuman jonosta. Luodaan siis Viestin käsittelijä vuonna app1/Handler/StatusUpdateHandler.php
polku:
käytä PsrLogLoggerInterface;
use 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);
// loput liiketoimintalogiikasta, eli sähköpostin lähettäminen käyttäjälle.
// $this->emailService->email()
}
}
Lähdekoodi saatavilla suoraan: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php
PHP attribuutit helpottavat asioita huomattavasti ja tarkoittavat sitä, että tässä tapauksessa meidän ei tarvitse huolehtia automaattisesta kytkennästä tai huolto-ilmoituksesta. Toimialueen tapahtumia käsittelevä mikropalvelumme on valmis, on aika siirtyä toiseen sovellukseen.
Tarkastelemme app2
hakemistoon ja toinen Symfony-sovellus. Ajatuksenamme on lähettää viesti jonoon, kun työntekijälle annetaan tehtävä järjestelmässä. Tehdään siis AMQP:n nopea konfigurointi ja saadaan toinen mikropalvelumme aloittamaan julkaiseminen. StatusUpdate
tapahtumat viestiväylään.
Kirjastojen asentaminen on täsmälleen sama kuin ensimmäisen sovelluksen kohdalla.
cd ..
cd app2/
symfony composer req amqp ampq-messenger monolog
Varmistetaan, että app2/.env
tiedosto sisältää kelvollisen DSN-merkinnän RabbitMQ:lle:
(...)
MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq:5672/%2f/messages
(...)
Jäljellä on enää Symfony Messengerin konfigurointi osoitteessa app2/config/packages/messenger.yaml
file:
puitteet:
Messenger:
# Ota tämä (ja alla oleva epäonnistunut kuljetus) kommentti pois, jos haluat lähettää epäonnistuneet viestit tähän kuljetukseen myöhempää käsittelyä varten.
# failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
reititys:
# Reititä viestisi kuljetuksiin.
'AppMessageStatusUpdate': async
Kuten näet, tällä kertaa kuljetusmäärittely osoittaa suoraan osoitteeseen async
ja määrittelee reitityksen lähettämällä meidän StatusUpdate
viesti määritettyyn DSN:ään. Tämä on ainoa konfigurointialue, jäljellä on enää AMQP-jonon logiikan ja toteutuskerroksen luominen. Tätä varten luomme kaksoiskappaleen StatusUpdateHandler
ja StatusUpdate
luokat app2
.
käytä PsrLogLoggerInterface;
use 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);
## liiketoimintalogiikka, esim. sisäisen ilmoituksen lähettäminen tai jonoon asettaminen joihinkin muihin järjestelmiin.
}
}
{
public function __construct(protected string $status){}
public function getStatus(): string
{
return $this->status;
}
}
Lähdekoodi saatavilla suoraan: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php
Lopuksi on vain luotava tapa lähettää viesti viestiväylään. Luomme yksinkertaisen Symfony-komento tätä varten:
käytä SymfonyComponentConsoleAttributeAsCommand;
use SymfonyComponentConsoleConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentMessengerMessageBusInterface;
[AsCommand(
name: "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 = "Worker X assigned to Y";
$this->messageBus->dispatch(
message: new StatusUpdate($status)
);
return Command::SUCCESS;
}
}
Kiitos Riippuvuuden injektio voimme käyttää instanssia MessageBusInterface
komennossamme ja lähetämme StatusUpdate
viestiä dispatch()
metodia jonoon. Lisäksi käytämme tässä myös PHP-attribuutteja.
Siinä kaikki - jäljellä on enää Docker Compose -ympäristön käyttäminen ja sovellusten käyttäytymisen seuraaminen.
Docker Composen avulla kontit, joissa on kaksi sovellustamme, rakennetaan ja ajetaan erillisinä instansseina. rabbitmq
kontti ja Message Bus -toteutuksemme.
Suorita seuraavat komennot projektin juurihakemistosta:
cd ../ # varmista, että olet päähakemistossa.
docker-compose up --build -d
Tämä komento voi kestää jonkin aikaa, koska se rakentaa kaksi erillistä säiliötä, joissa on PHP 8.1 + AMQP ja vetää RabbitMQ-kuvaa. Ole kärsivällinen. Kun kuvat on rakennettu, voit käynnistää komentomme osoitteesta app2
ja lähettää joitakin viestejä jonoon.
docker exec -it app2 php bin/console app:send
Voit tehdä sen niin monta kertaa kuin pystyt. Niin kauan kuin ei ole kuluttaja viestejäsi ei käsitellä. Heti kun käynnistät app1
ja kuluttaa kaikki viestit, jotka näytetään näytölläsi.
docker exec -it app1 php bin/console messenger:consume -vvv external_messages
Täydellinen lähdekoodi yhdessä README:n kanssa löytyy julkisesta arkistostamme. The Codest Github
Symfony kirjastojensa ja työkalujensa avulla mahdollistaa nopean ja tehokkaan lähestymistavan modernin version kehittämiseen. verkkosovellukset. Muutamalla komennolla ja muutamalla koodirivillä voimme luoda nykyaikaisen sovellusten välisen viestintäjärjestelmän. Symfony, kuten PHPon ihanteellinen web-sovellusten kehittäminen ja sen ekosysteemin ja helpon käyttöönoton ansiosta tämä ekosysteemi saavuttaa joitakin parhaita markkinoille tuloaikamittareita.
Nopea ei kuitenkaan aina tarkoita hyvää - edellä olevassa esimerkissä esiteltiin yksinkertaisin ja nopein tapa kommunikoida. Tarkkasilmäisimmät huomaavat varmasti, että sovelluskerroksen ulkopuolella olevien toimialueen tapahtumien erottaminen puuttuu - nykyisessä versiossa ne on päällekkäin, eikä täydellistä tukea ole olemassa Kirjekuori
, muun muassa ei ole Postimerkit
. Niitä ja muita varten kutsun sinut lukemaan osan II, jossa käsittelemme Symfony-sovellusten toimialueen rakenteen yhtenäistämistä mikropalveluympäristössä ja keskustelemme toisesta suositusta mikropalvelujen viestintämenetelmästä - tällä kertaa synkronisesta, REST API:han perustuvasta menetelmästä.