Микросервисы на PHP: архитектура и практика
В современной веб-разработке монолитная архитектура всё чаще уступает место микросервисной. PHP, традиционно ассоциирующийся с монолитами (WordPress, Laravel-монолит), отлично подходит для построения распределённых систем. В этой статье мы разберём ключевые принципы микросервисной архитектуры на PHP, рассмотрим практические примеры кода и инструменты, которые помогут вам перейти от монолита к гибкой системе.
Что такое микросервисы и зачем они нужны на PHP
Микросервисная архитектура — это подход, при котором приложение разбивается на несколько независимых сервисов. Каждый сервис отвечает за свою бизнес-логику (аутентификация, платежи, уведомления) и может быть разработан, развёрнут и масштабирован отдельно.
Почему PHP подходит для микросервисов:
- Быстрый старт — PHP-фреймворки (Laravel, Symfony, Lumen) позволяют создать сервис за считанные минуты.
- Большое сообщество — тысячи готовых пакетов для работы с очередями, API и базами данных.
- Гибкость — можно комбинировать PHP с другими языками (Go, Python) в одной системе.
Однако помните: микросервисы добавляют сложность. Не стоит дробить проект, если у вас небольшое приложение. Начните с монолита, а затем выделяйте сервисы по мере роста.
Архитектура типичного микросервиса на PHP
Рассмотрим базовую структуру одного сервиса. Допустим, у нас есть сервис UserService, отвечающий за регистрацию и авторизацию пользователей.
Структура проекта:
user-service/
├── api/
│ └── index.php # точка входа (REST API)
├── src/
│ ├── Controllers/
│ │ └── AuthController.php
│ ├── Models/
│ │ └── User.php
│ ├── Services/
│ │ └── AuthService.php
│ └── Database/
│ └── migrations/
├── config/
│ └── database.php
├── composer.json
├── Dockerfile
└── .env
Каждый сервис:
- Имеет собственный репозиторий и базу данных (часто PostgreSQL или MySQL).
- Общается с внешним миром через REST API или gRPC.
- Упакован в Docker-контейнер.
Пример простого REST-контроллера на Lumen (микро-фреймворк Laravel):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class AuthController extends Controller
{
public function register(Request $request)
{
// Валидация
$this->validate($request, [
'email' => 'required|email|unique:users',
'password' => 'required|min:8'
]);
// Создание пользователя
$user = User::create([
'email' => $request->input('email'),
'password' => app('hash')->make($request->input('password'))
]);
return response()->json(['user_id' => $user->id], 201);
}
}
Обмен данными между сервисами: синхронный и асинхронный
Микросервисы не могут существовать изолированно. Есть два основных способа коммуникации:
1. Синхронный (HTTP/REST)
Сервис A напрямую вызывает API сервиса B. Просто, но создаёт жёсткую связь.
<?php
// В сервисе OrderService
$httpClient = new \GuzzleHttp\Client();
$response = $httpClient->post('http://user-service/api/validate', [
'json' => ['token' => $token]
]);
if ($response->getStatusCode() === 200) {
// Пользователь валиден
}
2. Асинхронный (очереди / RabbitMQ)
Сервис отправляет сообщение в брокер (RabbitMQ, Kafka), а другой сервис обрабатывает его в фоне. Это снижает нагрузку и делает систему отказоустойчивее.
Пример отправки события через RabbitMQ с библиотекой php-amqplib:
<?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('order_created', false, true, false, false);
$data = json_encode([
'order_id' => 123,
'user_email' => 'user@example.com'
]);
$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'order_created');
echo " [x] Sent 'Order Created!'\n";
$channel->close();
$connection->close();
На стороне получателя (сервис уведомлений) запускается воркер:
<?php
// consumer.php
$callback = function ($msg) {
$data = json_decode($msg->body, true);
// Отправляем email пользователю
mail($data['user_email'], 'Заказ создан', 'Ваш заказ #' . $data['order_id'] . ' принят.');
$msg->ack();
};
$channel->basic_consume('order_created', '', false, false, false, false, $callback);
Инструменты для работы с микросервисами на PHP
Чтобы управлять микросервисами в продакшене, вам понадобятся:
- Docker + Docker Compose — упаковка каждого сервиса в контейнер. Пример
docker-compose.yml:
version: '3.8'
services:
user-service:
build: ./user-service
ports:
- "8001:80"
environment:
- DB_HOST=user-db
depends_on:
- user-db
user-db:
image: postgres:13
environment:
POSTGRES_DB: users
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
rabbitmq:
image: rabbitmq:3-management
ports: