PHP 8.2: 새로운 기능은 무엇인가요?
PHP의 새 버전이 곧 출시됩니다. 새롭게 구현된 기능에는 어떤 것들이 있나요? 이 글을 통해 알아보세요!
Symfony 프레임워크의 마이크로서비스 통신과 가장 널리 사용되는 방법인 RabbitMQ를 사용한 AMQP 통신에 관한 PHP 시리즈의 첫 번째 부분을 읽어보세요.
최신 애플리케이션 아키텍처로 인해 개발자는 IT 시스템의 여러 구성 요소 간의 통신에 대한 사고 방식을 바꿔야 했습니다. 과거에는 대부분의 시스템이 비즈니스 로직 연결 네트워크로 서로 연결된 모놀리식 구조로 만들어졌기 때문에 문제가 더 간단했습니다. 이러한 종속성을 유지하려면 PHP 프로젝트 에게는 큰 도전이었습니다. PHP 개발자의 인기가 높아지고 있으며, SaaS 솔루션의 인기도 크게 증가하고 있습니다. 클라우드 서비스로 인해 오늘날 마이크로서비스와 애플리케이션 모듈화에 대해 점점 더 많이 듣게 되었습니다.
그렇다면 독립적인 마이크로서비스를 만들어 서로 정보를 교환하게 하려면 어떻게 해야 할까요?
이 문서는 다음에 대한 시리즈 게시물 중 첫 번째 게시물입니다. 심포니의 마이크로서비스 커뮤니케이션 프레임워크와 가장 널리 사용되는 방법인 RabbitMQ를 사용한 AMQP 통신을 다룹니다.
두 개의 독립적인 애플리케이션을 만들고 메시지 버스만 사용하여 애플리케이션 간 통신을 수행합니다.
가상의 독립적인 두 가지 애플리케이션이 있습니다:
* app1
직원에게 이메일 및 SMS 알림을 전송합니다.
* app2
를 사용하여 직원의 업무를 관리하고 작업을 할당할 수 있습니다.
우리는 직원에게 업무를 할당하는 현대적이고 간단한 시스템을 만들고자 합니다. app2
를 사용하여 고객에게 알림을 보냅니다. app1
. 겉보기와 달리 이것은 매우 간단합니다!
이 글의 목적에 따라 최신 Symfony(작성 당시 버전 6.1)와 최신 버전의 PHP(8.1)를 사용하겠습니다. 아주 간단한 몇 단계로 두 개의 마이크로서비스로 작동하는 로컬 Docker 환경을 만들겠습니다. 필요한 것은
* 작동 중인 컴퓨터,
* 설치된 도커 + 도커 컴포즈 환경
* 및 로컬로 구성된 Symfony CLI 그리고 자유 시간.
애플리케이션 가상화 및 컨테이너화 도구로서 Docker의 기능을 사용하겠습니다. 먼저 다음 두 가지를 위한 프레임워크인 디렉터리 트리를 만들어 보겠습니다. Symfony 애플리케이션를 사용하여 환경의 인프라를 설명합니다. docker-compose.yml
파일을 만듭니다.
cd ~
mkdir 마이크로서비스-인-심포니
cd 마이크로서비스-인-심포니
심포니 새 앱1
심포니 새 앱2
docker-compose.yml 터치
두 개의 개별 Symfony 애플리케이션에 대해 두 개의 디렉터리를 만들고 빈 디렉터리를 만들었습니다. docker-compose.yml
파일을 실행하여 환경을 시작합니다.
다음 섹션을 다음 섹션에 추가해 보겠습니다. docker-compose.yml
file:
버전: '3.8'
서비스:
app1:
컨테이너명: app1
빌드: app1/.
restart: on-failure
환경 파일: app1/.env
환경:
앱 이름: app1
tty: true
stdinopen: true
app2:
컨테이너명: app2
빌드: app2/.
restart: on-failure
환경 파일: app2/.env
환경:
앱 이름: app2
tty: true
stdinopen: true
rabbitmq:
컨테이너명: rabbitmq
이미지: rabbitmq:관리
포트:
- 15672:15672
- 5672:5672
환경
- RABBITMQDEFAULTUSER=사용자
- RABBITMQDEFAULT_PASS=password
출처 코드 직접 사용할 수 있습니다: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml
하지만 잠깐, 여기서 무슨 일이 일어났을까요? Docker에 익숙하지 않은 분들에게는 위의 구성 파일이 수수께끼처럼 보일 수 있지만, 그 목적은 매우 간단합니다. Docker Compose를 사용하여 세 가지 "서비스"를 빌드하고 있습니다:
제대로 작동하려면 여전히 다음이 필요합니다. 도커파일
파일에 이미지를 빌드하는 소스가 있습니다. 이제 만들어 보겠습니다:
앱1/Docker파일을 터치합니다.
앱2/Docker파일을 터치합니다.
두 파일은 구조가 완전히 동일하며 다음과 같이 보입니다:
FROM php:8.1
COPY --from=composer:최신 /usr/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 &&
인스톨-php-익스텐션 AMQP
RUN 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/*
docker-php-ext-install zip을 실행합니다;
CMD bash -c "cd /app && composer install && php -a"
소스 코드를 직접 사용할 수 있습니다: /thecodest-co/microservices-in-symfony/blob/main/app1/Dockerfile
위 파일은 Docker Compose에서 Composer와 AMQP 확장자가 설치된 PHP 8.1 이미지에서 컨테이너를 빌드하는 데 사용됩니다. 또한 컨테이너를 백그라운드에서 계속 실행하기 위해 PHP 인터프리터를 추가 모드에서 실행합니다.
이제 디렉토리와 파일 트리가 다음과 같이 표시됩니다:
.
├── app1
│ └── 도커파일
| (...) # 심포니 앱 구조
├── app2
│ └── 도커파일
| (...) # Symfony 앱 구조
└── docker-compose.yml
먼저 app1
디렉터리와 첫 번째 애플리케이션으로 이동합니다.
이 예제에서는 다음에서 보낸 대기열의 메시지를 수신하고 소비하는 애플리케이션입니다. app2
요구 사항에 설명된 대로
에서 작업자에게 작업을 할당합니다.
app2
는 클라이언트에 알림을 보냅니다.
필요한 라이브러리를 추가하는 것부터 시작해 보겠습니다. AMQP는 기본적으로 심포니/메신저
확장 프로그램을 설치하세요. 추가로 설치해 드립니다. 독백/모놀로그
를 사용하여 시스템 로그를 추적하여 애플리케이션 동작을 쉽게 분석할 수 있습니다.
CD APP1/
심포니 작곡가 요청 AMQP 앰프 앰프-메신저 모노로그
설치 후 아래에 추가 파일이 추가되었습니다. config/packages/messenger.yaml
. 이 파일은 심포니 메신저 구성 요소에 대한 구성 파일이며 전체 구성.
아래의 YAML 파일로 교체합니다:
프레임워크:
메신저:
# 나중에 처리할 수 있도록 이 전송에 실패한 메시지를 보내려면 이 전송(및 아래의 실패한 전송)에 주석을 달지 마세요.
# 실패_전송: 실패했습니다.
전송:
# https://symfony.com/doc/current/messenger.html#transport-configuration
external_messages:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
옵션
auto_setup: false
exchange:
이름: 메시지
유형: 직접
default_publish_routing_key: from_external
대기열:
messages:
바인딩_키: [from_external]
소스 코드를 직접 사용할 수 있습니다: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml
Symfony Messenger는 Symfony 애플리케이션에서 동기 및 비동기 통신에 사용됩니다. 다양한 전송또는 전송 계층의 진실 소스입니다. 이 예제에서는 RabbitMQ 이벤트 큐 시스템을 지원하는 AMQP 확장을 사용합니다.
위의 구성은 다음과 같은 새 전송을 정의합니다. 외부_메시지
를 참조하는 메신저_운송_DSN
환경 변수에서 직접 듣기를 정의하고 메시지
채널로 이동합니다. 이 시점에서 app1/.env
파일을 열고 적절한 전송 주소를 추가합니다.
“`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 함수 __construct(보호된 문자열 $status){}
public function getStatus(): string
{
$this->status를 반환합니다;
}
}
소스 코드를 직접 사용할 수 있습니다: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php
마이크로서비스가 큐에서 위의 이벤트를 수신할 때 비즈니스 로직을 구현할 클래스가 여전히 필요합니다. 따라서 메시지 핸들러 에서 앱1/핸들러/상태업데이트핸들러.php
경로:
PsrLogLoggerInterface를 사용합니다;
심포니 컴포넌트 메신저 어트리뷰트를 메시지 핸들러로 사용합니다;
[AsMessageHandler]
클래스 StatusUpdateHandler
{
public function __construct(
protected LoggerInterface $logger,
) {}
public function __invoke(StatusUpdate $statusUpdate): void
{
$statusDescription = $statusUpdate->getStatus();
$this->logger->warning('APP1: {STATUS_UPDATE} - '.$statusDescription);
// 나머지 비즈니스 로직, 즉 사용자에게 이메일 보내기
// $this->emailService->email()
}
}
소스 코드를 직접 사용할 수 있습니다: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php
PHP 속성을 사용하면 작업이 훨씬 쉬워지며 이 특별한 경우에는 자동 배선이나 서비스 선언에 대해 걱정할 필요가 없습니다. 도메인 이벤트를 처리하기 위한 마이크로서비스가 준비되었으니 이제 두 번째 애플리케이션으로 넘어갈 차례입니다.
이번 블로그에서는 app2
디렉터리와 두 번째 Symfony 애플리케이션. 우리의 아이디어는 작업자가 시스템에서 작업을 할당받을 때 대기열에 메시지를 보내는 것입니다. 이제 AMQP를 빠르게 구성하고 두 번째 마이크로서비스가 게시를 시작하도록 해 보겠습니다. 상태 업데이트
이벤트를 메시지 버스로 전송합니다.
라이브러리를 설치하는 방법은 첫 번째 애플리케이션과 완전히 동일합니다.
cd ..
cd app2/
심포니 작곡가 요청 AMQP 앰프 앰프-메신저 독백
다음 사항을 확인해 보겠습니다. app2/.env
파일에 RabbitMQ에 대한 유효한 DSN 항목이 포함되어 있습니다:
(...)
MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq:5672/%2f/messages
(...)
이제 남은 것은 심포니 메신저를 구성하는 것뿐입니다. app2/config/packages/messenger.yaml
file:
프레임워크:
메신저:
# 나중에 처리할 수 있도록 이 전송에 실패한 메시지를 보내려면 이 전송(및 아래의 실패한 전송)에 주석을 달지 마세요.
# 실패_전송: 실패했습니다.
전송:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
라우팅:
# 메시지를 전송으로 라우팅합니다.
'앱메시지상태업데이트': 비동기
보시다시피, 이번에는 전송 정의가 다음을 직접 가리킵니다. 비동기
를 전송하는 형태로 라우팅을 정의합니다. 상태 업데이트
메시지를 구성한 DSN으로 전송합니다. 이것은 구성의 유일한 영역이며, 남은 것은 AMQP 대기열의 로직과 구현 계층을 만드는 것뿐입니다. 이를 위해 쌍둥이 상태 업데이트 핸들러
그리고 상태 업데이트
클래스의 app2
.
PsrLogLoggerInterface를 사용합니다;
심포니 컴포넌트 메신저 어트리뷰트를 메시지 핸들러로 사용합니다;
[AsMessageHandler]
클래스 StatusUpdateHandler
{
공용 함수 __construct(
비공개 읽기 전용 로거 인터페이스 $logger,
) {}
public function __invoke(StatusUpdate $statusUpdate): void
{
$statusDescription = $statusUpdate->getStatus();
$this->logger->warning('APP2: {STATUS_UPDATE} - '.$statusDescription);
## 비즈니스 로직, 즉 내부 알림 전송 또는 일부 다른 시스템 큐에 대기 중
}
}
{
public 함수 __construct(보호된 문자열 $status){}
public function getStatus(): string
{
$this->status를 반환합니다;
}
}
소스 코드를 직접 사용할 수 있습니다: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php
마지막으로, 메시지 버스로 메시지를 보내는 방법을 만들기만 하면 됩니다. 간단한 Symfony 명령 를 사용하세요:
심포니컴포넌트 콘솔 어트리뷰트를 명령으로 사용합니다;
사용 심포니 컴포넌트 콘솔 커맨드 커맨드;
사용 심포니 컴포넌트 콘솔 입력 입력 인터페이스;
사용 심포니 컴포넌트 콘솔 출력 출력 인터페이스;
심포니컴포넌트메신저메시지버스인터페이스를 사용합니다;
[AsCommand(
이름: "app:send"
)]
SendStatusCommand 클래스는 Command를 확장합니다.
{
공용 함수 construct(private 읽기 전용 MessageBusInterface $messageBus, 문자열 $name = null)
{
parent::construct($name);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$status = "작업자 X가 Y에 할당됨";
$this->messageBus->dispatch(
message: new StatusUpdate($status)
);
Command::SUCCESS를 반환합니다;
}
}
덕분에 종속성 주입 의 인스턴스를 사용할 수 있습니다. 메시지 버스 인터페이스
명령에서 상태 업데이트
메시지를 통해 dispatch()
메서드를 대기열에 추가합니다. 또한 여기에서는 PHP 속성도 사용합니다.
이제 Docker Compose 환경을 실행하고 애플리케이션이 어떻게 작동하는지 확인하는 일만 남았습니다.
Docker Compose를 사용하면 두 애플리케이션이 포함된 컨테이너가 별도의 인스턴스로 빌드되고 실행되며, 유일한 미들웨어 계층은 rabbitmq
컨테이너와 메시지 버스 구현.
프로젝트의 루트 디렉토리에서 다음 명령을 실행해 보겠습니다:
cd ../ # 메인 디렉터리에 있는지 확인합니다.
도커-컴포즈 업 --build -d
이 명령은 PHP 8.1 + AMQP로 두 개의 별도 컨테이너를 빌드하고 RabbitMQ 이미지를 가져오기 때문에 시간이 다소 걸릴 수 있습니다. 조금만 기다려주세요. 이미지가 빌드되면 다음에서 명령을 실행할 수 있습니다. app2
를 클릭하고 대기열에 메시지를 보냅니다.
docker exec -it app2 php bin/console app:send
얼마든지 할 수 있습니다. 단 소비자 를 누르면 메시지가 처리되지 않습니다. 메시지를 실행하자마자 app1
를 클릭하고 화면에 표시되는 모든 메시지를 소비합니다.
도커 실행 -it app1 php bin/콘솔 메신저:소비 -vv 외부_메시지
전체 소스 코드 사용 설명서와 함께 공개 저장소에서 찾을 수 있습니다. The Codest 깃허브
라이브러리와 툴을 갖춘 Symfony를 사용하면 빠르고 효율적인 방식으로 최신 웹 애플리케이션. 몇 가지 명령과 몇 줄의 코드만으로 애플리케이션 간에 최신 통신 시스템을 만들 수 있습니다. Symfony와 같은 PHP에 이상적입니다. 웹 애플리케이션 개발 에코시스템과 구현의 용이성 덕분에 이 에코시스템은 최고의 출시 기간 지표를 달성하고 있습니다.
그러나 빠르다고 해서 항상 좋은 것은 아닙니다. 위의 예에서는 가장 간단하고 빠른 통신 방법을 제시했습니다. 더 호기심이 많은 사람들은 애플리케이션 계층 외부에서 도메인 이벤트의 단절이 부족하다는 것을 확실히 알아차릴 것입니다. 현재 버전에서는 중복되어 있으며 다음에 대한 완전한 지원이 없습니다. 봉투
무엇보다도 스탬프
. 이러한 분들을 위해 2부에서는 마이크로서비스 환경에서 Symfony 애플리케이션의 도메인 구조를 통합하는 주제를 다루고, 두 번째로 널리 사용되는 마이크로서비스 통신 방법인 REST API 기반의 동기식 통신 방법에 대해 설명합니다.