Введение: почему C++ для микросервисов?
Микросервисная архитектура прочно вошла в мир разработки, но традиционно ассоциируется с языками вроде Go, Java или Python. Однако C++ остается незаменимым там, где критичны производительность, низкая задержка и эффективное использование памяти. В этой статье мы разберем, как строить микросервисы на C++, какие библиотеки использовать и как организовать инфраструктуру.
Основные преимущества C++ в микросервисах:
- Максимальная производительность (нативно компилируемый код)
- Минимальное потребление памяти
- Полный контроль над ресурсами
- Отсутствие сборщика мусора (предсказуемые задержки)
Мы рассмотрим архитектуру, реализацию REST API, gRPC, работу с очередями и контейнеризацию на практических примерах.
Архитектура микросервиса на C++
Базовые принципы
Микросервис на C++ должен быть:
- Автономным — каждый сервис работает независимо
- Слабо связанным — минимальные зависимости между сервисами
- Ориентированным на бизнес-функции — один сервис решает одну задачу
- Устойчивым к сбоям — graceful degradation
Типовая структура проекта
my_microservice/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ ├── server/
│ │ ├── http_server.cpp
│ │ └── http_server.h
│ ├── service/
│ │ ├── order_service.cpp
│ │ └── order_service.h
│ ├── repository/
│ │ ├── order_repository.cpp
│ │ └── order_repository.h
│ └── config/
│ ├── config.cpp
│ └── config.h
├── include/
│ └── (публичные заголовки)
├── tests/
│ └── test_order_service.cpp
└── Dockerfile
Практическая реализация: REST API микросервис
Выбор HTTP-библиотеки
Для C++ лучшие варианты — cpp-httplib (легковесная, header-only) и Drogon (полнофункциональный фреймворк). Рассмотрим пример с cpp-httplib.
Пример: сервис управления заказами
// main.cpp
#include <httplib.h>
#include <nlohmann/json.hpp>
#include <iostream>
#include <memory>
#include "order_service.h"
using json = nlohmann::json;
int main() {
httplib::Server svr;
auto orderService = std::make_shared<OrderService>();
// POST /orders — создание заказа
svr.Post("/orders", [orderService](const httplib::Request& req, httplib::Response& res) {
try {
auto data = json::parse(req.body);
auto order = orderService->createOrder(data);
res.set_content(order.dump(), "application/json");
res.status = 201;
} catch (const std::exception& e) {
res.set_content(json{{"error", e.what()}}.dump(), "application/json");
res.status = 400;
}
});
// GET /orders/{id} — получение заказа
svr.Get(R"(/orders/(\d+))", [orderService](const httplib::Request& req, httplib::Response& res) {
int orderId = std::stoi(req.matches[1]);
auto order = orderService->getOrder(orderId);
if (order) {
res.set_content(order->dump(), "application/json");
} else {
res.status = 404;
res.set_content(json{{"error", "Order not found"}}.dump(), "application/json");
}
});
std::cout << "Server started on port 8080" << std::endl;
svr.listen("0.0.0.0", 8080);
return 0;
}
// order_service.cpp
#include "order_service.h"
#include <stdexcept>
using json = nlohmann::json;
json OrderService::createOrder(const json& data) {
if (!data.contains("product_id") || !data.contains("quantity")) {
throw std::invalid_argument("Missing required fields");
}
Order order;
order.id = nextId_++;
order.productId = data["product_id"];
order.quantity = data["quantity"];
order.status = "created";
orders_[order.id] = order;
json result;
result["id"] = order.id;
result["product_id"] = order.productId;
result["quantity"] = order.quantity;
result["status"] = order.status;
return result;
}
std::optional<json> OrderService::getOrder(int id) {
auto it = orders_.find(id);
if (it == orders_.end()) {
return std::nullopt;
}
json result;
result["id"] = it->second.id;
result["product_id"] = it->second.productId;
result["quantity"] = it->second.quantity;
result["status"] = it->second.status;
return result;
}
Сборка с CMake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(order_service)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Зависимости
include(FetchContent)
FetchContent_Declare(
cpp-httplib
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
GIT_TAG v0.12.0
)
FetchContent_MakeAvailable(cpp-httplib)
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.2
)
FetchContent_MakeAvailable(nlohmann_json)
add_executable(order_service
src/main.cpp
src/service/order_service.cpp
)
target_include_directories(order_service PRIVATE include)
target_link_libraries(order_service PRIVATE httplib::httplib nlohmann_json::nlohmann_json)
Межсервисное взаимодействие: gRPC и очереди
gRPC на C++
Для высоконагруженных систем gRPC предпочтительнее REST. Используем библиотеку gRPC C++.
// proto/order.proto
syntax = "proto3";
package order;
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (OrderResponse);
rpc GetOrder (GetOrderRequest) returns (OrderResponse);
}
message CreateOrderRequest {
string product_id = 1;
int32 quantity =