Введение: Почему PHP и микросервисы?
Долгое время PHP ассоциировался исключительно с монолитными приложениями — WordPress, Laravel или Symfony. Однако современный PHP (начиная с версии 7.4 и особенно 8.x) превратился в мощный инструмент для построения микросервисной архитектуры. Благодаря улучшенной производительности, строгой типизации, асинхронным возможностям (через ReactPHP или Swoole) и зрелой экосистеме, PHP стал полноценным языком для микросервисов.
В этой статье мы разберем: что такое микросервисы на PHP, как спроектировать архитектуру, какие технологии использовать, и напишем реальные примеры кода.
Что такое микросервисная архитектура?
Микросервисы — это подход, при котором приложение разбивается на небольшие, независимо развертываемые сервисы. Каждый сервис отвечает за свою бизнес-функцию и общается с другими через сеть (HTTP/REST, gRPC, очереди сообщений).
Ключевые принципы микросервисов на PHP
- Независимость — каждый сервис может быть написан на PHP, Node.js или Go, но мы используем PHP для всех.
- Децентрализация данных — каждая база данных принадлежит только одному сервису.
- Оркестрация vs Хореография — выбор между центральным управлением (Kubernetes) и событийно-ориентированным подходом.
- Отказоустойчивость — один упавший сервис не должен ломать всю систему.
Архитектура микросервисов на PHP: от теории к практике
Рассмотрим типичный проект: интернет-магазин. Разобьем его на микросервисы:
- User Service — регистрация, аутентификация, профили.
- Product Service — каталог товаров, цены, остатки.
- Order Service — создание заказов, статусы.
- Payment Service — обработка платежей.
- Notification Service — email/SMS уведомления.
Шаг 1: Проектирование API Gateway
API Gateway — единая точка входа. На PHP его можно реализовать на Slim Framework или с помощью Nginx + PHP-FPM. Пример простого gateway на Slim 4:
<?php
// api-gateway/public/index.php
use Slim\Factory\AppFactory;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Маршрутизация к микросервисам
$app->post('/api/orders', function (Request $request, Response $response) {
// Перенаправляем запрос в Order Service
$client = new GuzzleHttp\Client(['base_uri' => 'http://order-service:8080']);
$res = $client->post('/orders', [
'json' => $request->getParsedBody()
]);
$response->getBody()->write($res->getBody());
return $response->withStatus($res->getStatusCode());
});
$app->run();
Шаг 2: Синхронное взаимодействие (REST)
Самый простой способ — HTTP-запросы между сервисами. Используем Guzzle или Symfony HttpClient. Пример Product Service:
<?php
// product-service/src/Controller/ProductController.php
namespace App\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class ProductController
{
public function getProduct(int $id): JsonResponse
{
// Логика получения товара из БД
$product = $this->productRepository->find($id);
if (!$product) {
return new JsonResponse(['error' => 'Product not found'], 404);
}
return new JsonResponse([
'id' => $product->getId(),
'name' => $product->getName(),
'price' => $product->getPrice()
]);
}
}
Шаг 3: Асинхронное взаимодействие (RabbitMQ)
Для событий, не требующих мгновенного ответа (уведомления, обновление кэша), используем очереди. Установите php-amqplib:
<?php
// notification-service/src/Consumer/EmailConsumer.php
require_once __DIR__ . '/../../vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('email_queue', false, true, false, false);
echo " [*] Waiting for messages. To exit press CTRL+C\n";
$callback = function (AMQPMessage $msg) {
$data = json_decode($msg->body, true);
// Отправляем email
mail($data['email'], $data['subject'], $data['body']);
echo " [x] Sent email to {$data['email']}\n";
};
$channel->basic_consume('email_queue', '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
$channel->wait();
}
Шаг 4: Базы данных и транзакции
Каждый микросервис имеет свою БД. Для распределенных транзакций используем паттерн Saga. Пример на PHP с Doctrine ORM:
<?php
// order-service/src/Saga/CreateOrderSaga.php
class CreateOrderSaga
{
public function execute(array $orderData): void
{
try {
// Шаг 1: Резервируем товары
$this->productServiceClient->reserveStock($orderData['product_id'], $orderData['quantity']);
// Шаг 2: Создаем заказ
$order = new Order($orderData);
$this->entityManager->persist($order);
$this->entityManager->flush();
// Шаг 3: Инициируем платеж
$this->paymentServiceClient->processPayment($order->getId(), $orderData['amount']);
} catch (\Exception $e) {
// Компенсационные действия
$this->productServiceClient->releaseStock($orderData['product_id