Микросервисы — это не просто модный тренд. Это способ разбить большую систему на маленькие, независимые кусочки, которые легче разрабатывать, тестировать и масштабировать. Если вы PHP-разработчик и хотите попробовать себя в этой архитектуре, но не знаете, с чего начать, — эта статья для вас. Мы пройдём путь от пустой папки до работающего микросервиса, обсудим подводные камни и дадим практические советы.
Что такое микросервис и зачем он нужен
Представьте, что у вас есть интернет-магазин. В монолите всё свалено в одну кучу: корзина, оплата, уведомления, каталог. Поменяли что-то в корзине — пересобираем и перезапускаем всё приложение. Микросервисный подход предлагает разделить эту кучу на отдельные сервисы: сервис корзины, сервис оплаты, сервис уведомлений. Каждый живёт своей жизнью, общается с другими по сети (обычно через HTTP или очереди).
Главные плюсы: независимое развёртывание, масштабирование только нужного сервиса, возможность использовать разные технологии для разных задач. Минусы тоже есть: сложнее отлаживать, нужно следить за сетью и согласованностью данных. Но если система растёт, микросервисы могут спасти.
Выбор инструментов и подготовка окружения
Для PHP-микросервисов нам понадобится несколько вещей:
- Веб-сервер или встроенный сервер PHP (для разработки).
- Фреймворк для обработки HTTP-запросов. Можно взять Slim, Lumen или даже чистый PHP. Я рекомендую Slim — он лёгкий и не навязывает архитектуру.
- Менеджер зависимостей Composer.
- Docker для изоляции сервисов (по желанию, но очень удобно).
Установим Slim через Composer. Создадим папку проекта и выполним:
composer require slim/slim slim/psr7
Теперь создадим точку входа — файл public/index.php. Это будет наш первый микросервис, который просто отвечает на запросы.
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\ResponseFactory;
use Slim\Factory\ServerRequestFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = Slim\Factory\AppFactory::create();
$app->get('/hello/{name}', function (Request $request, Response $response, array $args) {
$name = $args['name'];
$response->getBody()->write("Hello, $name");
return $response;
});
$app->run();
Запустим встроенный сервер PHP:
php -S localhost:8080 -t public
Откройте в браузере http://localhost:8080/hello/World — увидите приветствие. Поздравляю, вы только что создали простейший микросервис!
Организация кода и взаимодействие между сервисами
Хороший микросервис должен быть маленьким и делать одну вещь. Например, сервис пользователей, сервис заказов, сервис платежей. Каждый сервис — отдельный проект со своим репозиторием и зависимостями.
Как они общаются? Чаще всего через HTTP/REST. Один сервис делает HTTP-запрос к другому. Для этого можно использовать библиотеку Guzzle.
Установим Guzzle:
composer require guzzlehttp/guzzle
Пример вызова другого сервиса из нашего кода:
<?php
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'http://users-service:8081',
'timeout' => 2.0,
]);
$response = $client->request('GET', '/users/123');
$data = json_decode($response->getBody(), true);
Важно продумать, что делать, если сервис недоступен. Нужны таймауты, повторные попытки, запасные варианты. Об этом ниже.
Обработка ошибок и отказоустойчивость
В микросервисной архитектуре сеть — самое слабое звено. Сервисы могут падать, тормозить, возвращать ошибки. Чтобы система не рушилась целиком, нужно применять паттерны отказоустойчивости.
Основные из них:
- Таймауты — не ждите ответа вечно.
- Повторные попытки (retry) — если запрос не удался, попробуйте ещё раз (но с ограничением).
- Предохранитель (circuit breaker) — если сервис часто падает, временно перестаньте к нему обращаться.
- Запасной вариант (fallback) — верните закешированные данные или значение по умолчанию.
В PHP есть библиотеки, например, php-circuit-breaker. Но можно реализовать простой предохранитель самостоятельно. Пример:
<?php
class CircuitBreaker {
private $failures = 0;
private $lastFailureTime = 0;
private $threshold = 3;
private $timeout = 60;
public function call(callable $service) {
if ($this->isOpen()) {
throw new Exception('Circuit is open');
}
try {
$result = $service();
$this->reset();
return $result;
} catch (Exception $e) {
$this->recordFailure();
throw $e;
}
}
private function isOpen() {
if ($this->failures < $this->threshold) {
return false;
}
if (time() - $this->lastFailureTime > $this->timeout) {
$this->reset();
return false;
}
return true;
}
private function recordFailure() {
$this->failures++;
$this->lastFailureTime = time();
}
private function reset() {
$this->failures = 0;
$this->lastFailureTime = 0;
}
}
Этот класс позволяет временно блокировать вызовы к проблемному сервису.
Логирование, мониторинг и развёртывание
Без логов и мониторинга микросервисы превращаются в чёрный ящик. Нужно понимать, что происходит в каждом сервисе. Используйте PSR-3 логгер, например, Monolog.
composer require monolog/monolog
Пример настройки логирования в Slim:
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('my_service');
$logger->pushHandler(new StreamHandler(__DIR__ . '/../logs/app.log', Logger::DEBUG));
$app->add(function ($request, $handler) use ($logger) {
$logger->info('Request', ['method' => $request->getMethod(), 'uri' => $request->getUri()]);
$response = $handler->handle($request);
$logger->info('Response', ['status' => $response->getStatusCode()]);
return $response;
});
Для мониторинга можно использовать Prometheus + Grafana. Но на первых порах достаточно смотреть логи и настроить простые health-check эндпоинты.
Развёртывание: каждый сервис упаковывается в Docker-образ и запускается отдельно. Можно использовать docker-compose для локальной разработки и Kubernetes для продакшена.
Пример Dockerfile для PHP-сервиса:
FROM php:8.1-apache
COPY . /var/www/html/
RUN docker-php-ext-install pdo pdo_mysql
EXPOSE 80
Не забудьте про CI/CD — автоматическую сборку и деплой. GitHub Actions или GitLab CI помогут.
Практические советы и типичные ошибки
Вот несколько советов, которые сэкономят вам время и нервы:
- Не делайте микросервисы слишком мелкими. Если сервис состоит из одной функции, это overhead. Балансируйте.
- Используйте API Gateway. Он будет единой точкой входа для клиентов и маршрутизировать запросы к сервисам.
- Продумайте версионирование API. Добавляйте префикс
/v1/в URL, чтобы не ломать клиентов при изменениях. - Автоматизируйте тестирование. Юнит-тесты и интеграционные тесты обязательны.
- Следите за состоянием сервисов. Health-check эндпоинт должен возвращать 200 OK, если сервис жив.
Типичные ошибки новичков:
- Синхронные вызовы между сервисами без таймаутов.
- Общая база данных для нескольких сервисов (это антипаттерн).
- Игнорирование идемпотентности операций (повторный запрос может создать дубликат).
Вот таблица, которая поможет выбрать способ взаимодействия между сервисами:
| Способ | Когда использовать | Плюсы | Минусы |
|---|---|---|---|
| HTTP/REST | Простые синхронные запросы | Простота, понятность | Зависимость от доступности |
| gRPC | Высокая производительность, строгие контракты | Быстро, эффективно | Сложнее в настройке |
| Очереди (RabbitMQ, Kafka) | Асинхронная обработка, развязка сервисов | Устойчивость к нагрузкам | Сложность отладки |
Заключение
Разработка PHP микросервисов с нуля — задача не на один день, но вполне решаемая. Начните с малого: сделайте один простой сервис, научитесь его деплоить и мониторить. Постепенно добавляйте новые. Главное — не усложняйте без необходимости и всегда думайте о том, как ваша система будет вести себя при сбоях.
Помните, что микросервисы — это инструмент, а не цель. Если монолит справляется, возможно, не стоит его ломать. Но если вы готовы — вперёд, экспериментируйте!
Студия WNDER



