api gateway example done | maybe need some cleanup
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"workspace": {
|
||||
"id": "18e02c0d-1edf-4046-b1c2-009c61873ba5"
|
||||
},
|
||||
"entities": {
|
||||
"collections": [],
|
||||
"environments": [],
|
||||
"specs": [],
|
||||
"flows": [],
|
||||
"globals": []
|
||||
}
|
||||
}
|
||||
+1
-14
@@ -1,20 +1,7 @@
|
||||
# Используем official Python runtime как базовый образ
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Устанавливаем рабочую директорию в контейнере
|
||||
WORKDIR /app
|
||||
|
||||
# Копируем файл зависимостей
|
||||
COPY requirements.txt .
|
||||
|
||||
# Устанавливаем зависимости
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Копируем код приложения
|
||||
COPY service-1-main.py main.py
|
||||
|
||||
# Экспонируем порт
|
||||
EXPOSE 8001
|
||||
|
||||
# Команда для запуска приложения
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
+1
-14
@@ -1,20 +1,7 @@
|
||||
# Используем official Python runtime как базовый образ
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Устанавливаем рабочую директорию в контейнере
|
||||
WORKDIR /app
|
||||
|
||||
# Копируем файл зависимостей
|
||||
COPY requirements.txt .
|
||||
|
||||
# Устанавливаем зависимости
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Копируем код приложения
|
||||
COPY service-2-main.py main.py
|
||||
|
||||
# Экспонируем порт
|
||||
EXPOSE 8002
|
||||
|
||||
# Команда для запуска приложения
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8002"]
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8002"]
|
||||
@@ -0,0 +1,381 @@
|
||||
# Примеры тестирования микросервисов через API Gateway KrakenD
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
.
|
||||
├── service-1-main.py # User Service
|
||||
├── service-2-main.py # Order Service
|
||||
├── requirements.txt # Зависимости
|
||||
├── Dockerfile.service1 # Docker образ для Service 1
|
||||
├── Dockerfile.service2 # Docker образ для Service 2
|
||||
├── docker-compose.yaml # Docker Compose без Gateway
|
||||
├── docker-compose-krakend.yaml # Docker Compose с KrakenD Gateway
|
||||
├── krakend-config.json # Конфигурация KrakenD
|
||||
└── README.md # Документация
|
||||
```
|
||||
|
||||
## Запуск контейнеров с KrakenD
|
||||
|
||||
```bash
|
||||
# Построить образы и запустить с KrakenD Gateway
|
||||
docker-compose -f docker-compose-krakend.yaml up --build
|
||||
|
||||
# Запустить в фоновом режиме
|
||||
docker-compose -f docker-compose-krakend.yaml up -d --build
|
||||
|
||||
# Просмотреть логи всех сервисов
|
||||
docker-compose -f docker-compose-krakend.yaml logs -f
|
||||
|
||||
# Просмотреть логи только KrakenD
|
||||
docker-compose -f docker-compose-krakend.yaml logs -f api-gateway
|
||||
|
||||
# Остановить контейнеры
|
||||
docker-compose -f docker-compose-krakend.yaml down
|
||||
```
|
||||
|
||||
## API Gateway KrakenD
|
||||
|
||||
### Что такое KrakenD?
|
||||
|
||||
KrakenD - это высокопроизводительный API Gateway с открытым исходным кодом, написанный на Go. Он обеспечивает:
|
||||
|
||||
- **Маршрутизацию запросов** к микросервисам
|
||||
- **Кэширование** ответов
|
||||
- **Rate limiting** (ограничение частоты запросов)
|
||||
- **CORS** (Cross-Origin Resource Sharing)
|
||||
- **Трансформацию данных** перед отправкой клиенту
|
||||
- **Логирование** запросов
|
||||
- **Мониторинг** производительности
|
||||
|
||||
### Порты сервисов
|
||||
|
||||
- **KrakenD Gateway**: `http://localhost:8000` (главный точка входа)
|
||||
- **Service 1**: `http://localhost:8001` (доступен также через Gateway)
|
||||
- **Service 2**: `http://localhost:8002` (доступен также через Gateway)
|
||||
|
||||
## Тестирование через KrakenD Gateway
|
||||
|
||||
### Health Check Gateway
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
### Статус всех сервисов
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/gateway/status
|
||||
```
|
||||
|
||||
## User Service Endpoints через Gateway
|
||||
|
||||
### Получить список пользователей
|
||||
```bash
|
||||
curl http://localhost:8000/users
|
||||
```
|
||||
|
||||
### Получить пользователя по ID
|
||||
```bash
|
||||
curl http://localhost:8000/users/1
|
||||
```
|
||||
|
||||
### Создать нового пользователя
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/users \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Петр Иванов",
|
||||
"email": "petr@example.com",
|
||||
"age": 30
|
||||
}'
|
||||
```
|
||||
|
||||
### Обновить пользователя
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/users/1 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Иван Петров (обновлено)",
|
||||
"email": "ivan.updated@example.com",
|
||||
"age": 29
|
||||
}'
|
||||
```
|
||||
|
||||
### Удалить пользователя
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8000/users/1
|
||||
```
|
||||
|
||||
### Получить статистику пользователей
|
||||
```bash
|
||||
curl http://localhost:8000/users/stats
|
||||
```
|
||||
|
||||
## Order Service Endpoints через Gateway
|
||||
|
||||
### Получить список продуктов
|
||||
```bash
|
||||
curl http://localhost:8000/products
|
||||
```
|
||||
|
||||
### Получить продукт по ID
|
||||
```bash
|
||||
curl http://localhost:8000/products/1
|
||||
```
|
||||
|
||||
### Создать новый продукт
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/products \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Мышка беспроводная",
|
||||
"price": 1500.00,
|
||||
"quantity": 20
|
||||
}'
|
||||
```
|
||||
|
||||
### Обновить продукт
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/products/1 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Ноутбук (обновлено)",
|
||||
"price": 55000.00,
|
||||
"quantity": 3
|
||||
}'
|
||||
```
|
||||
|
||||
### Удалить продукт
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8000/products/1
|
||||
```
|
||||
|
||||
### Получить список заказов
|
||||
```bash
|
||||
curl http://localhost:8000/orders
|
||||
```
|
||||
|
||||
### Получить заказ по ID
|
||||
```bash
|
||||
curl http://localhost:8000/orders/1
|
||||
```
|
||||
|
||||
### Создать новый заказ
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/orders \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"user_id": 2,
|
||||
"product_id": 2,
|
||||
"quantity": 2
|
||||
}'
|
||||
```
|
||||
|
||||
### Получить статистику заказов
|
||||
```bash
|
||||
curl http://localhost:8000/orders/stats
|
||||
```
|
||||
|
||||
## Тестирование через Python requests
|
||||
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
|
||||
# URL Gateway
|
||||
GATEWAY_URL = "http://localhost:8000"
|
||||
|
||||
def test_users():
|
||||
"""Тестирование User Service через Gateway"""
|
||||
print("=== Testing User Service ===")
|
||||
|
||||
# Получение списка пользователей
|
||||
response = requests.get(f"{GATEWAY_URL}/users")
|
||||
print(f"GET /users: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Получение конкретного пользователя
|
||||
response = requests.get(f"{GATEWAY_URL}/users/1")
|
||||
print(f"GET /users/1: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Создание пользователя
|
||||
user_data = {
|
||||
"name": "Тест Пользователь",
|
||||
"email": "test@example.com",
|
||||
"age": 25
|
||||
}
|
||||
response = requests.post(f"{GATEWAY_URL}/users", json=user_data)
|
||||
print(f"POST /users: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Получение статистики
|
||||
response = requests.get(f"{GATEWAY_URL}/users/stats")
|
||||
print(f"GET /users/stats: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
def test_products():
|
||||
"""Тестирование Order Service (Products) через Gateway"""
|
||||
print("=== Testing Product Service ===")
|
||||
|
||||
# Получение списка продуктов
|
||||
response = requests.get(f"{GATEWAY_URL}/products")
|
||||
print(f"GET /products: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Получение конкретного продукта
|
||||
response = requests.get(f"{GATEWAY_URL}/products/1")
|
||||
print(f"GET /products/1: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Создание продукта
|
||||
product_data = {
|
||||
"name": "Новый продукт",
|
||||
"price": 5000.00,
|
||||
"quantity": 10
|
||||
}
|
||||
response = requests.post(f"{GATEWAY_URL}/products", json=product_data)
|
||||
print(f"POST /products: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
def test_orders():
|
||||
"""Тестирование Order Service (Orders) через Gateway"""
|
||||
print("=== Testing Order Service ===")
|
||||
|
||||
# Получение списка заказов
|
||||
response = requests.get(f"{GATEWAY_URL}/orders")
|
||||
print(f"GET /orders: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Получение конкретного заказа
|
||||
response = requests.get(f"{GATEWAY_URL}/orders/1")
|
||||
print(f"GET /orders/1: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Создание заказа
|
||||
order_data = {
|
||||
"user_id": 1,
|
||||
"product_id": 2,
|
||||
"quantity": 2
|
||||
}
|
||||
response = requests.post(f"{GATEWAY_URL}/orders", json=order_data)
|
||||
print(f"POST /orders: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Получение статистики
|
||||
response = requests.get(f"{GATEWAY_URL}/orders/stats")
|
||||
print(f"GET /orders/stats: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
def test_gateway_status():
|
||||
"""Проверка статуса Gateway и всех сервисов"""
|
||||
print("=== Gateway Status ===")
|
||||
|
||||
# Health check Gateway
|
||||
response = requests.get(f"{GATEWAY_URL}/health")
|
||||
print(f"Gateway Health: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
# Статус всех сервисов
|
||||
response = requests.get(f"{GATEWAY_URL}/gateway/status")
|
||||
print(f"All Services Status: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_gateway_status()
|
||||
test_users()
|
||||
test_products()
|
||||
test_orders()
|
||||
print("✓ Все тесты завершены успешно!")
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("✗ Ошибка подключения. Убедитесь, что контейнеры запущены:")
|
||||
print(" docker-compose -f docker-compose-krakend.yaml up -d --build")
|
||||
except Exception as e:
|
||||
print(f"✗ Ошибка: {e}")
|
||||
```
|
||||
|
||||
## Конфигурация KrakenD (krakend-config.json)
|
||||
|
||||
### Основные параметры
|
||||
|
||||
- **version**: версия конфигурации (3)
|
||||
- **timeout**: глобальный таймаут для запросов (3s)
|
||||
- **cache_ttl**: время кэширования по умолчанию (300s)
|
||||
- **output_encoding**: формат ответа (json)
|
||||
|
||||
### Endpoints
|
||||
|
||||
Для каждого endpoint определяются:
|
||||
- **endpoint**: путь доступа через Gateway
|
||||
- **method**: HTTP метод (GET, POST, PUT, DELETE)
|
||||
- **backend**: список бэкенд сервисов для маршрутизации
|
||||
- **cache_ttl**: время кэширования для этого endpoint
|
||||
|
||||
### Пример endpoint конфигурации
|
||||
|
||||
```json
|
||||
{
|
||||
"endpoint": "/users/{id}",
|
||||
"method": "GET",
|
||||
"backend": [
|
||||
{
|
||||
"url_pattern": "/users/{id}",
|
||||
"method": "GET",
|
||||
"host": ["service-1:8001"],
|
||||
"disable_host_sanitize": false
|
||||
}
|
||||
],
|
||||
"output_encoding": "json",
|
||||
"cache_ttl": "60s"
|
||||
}
|
||||
```
|
||||
|
||||
### Extra Config (дополнительная конфигурация)
|
||||
|
||||
1. **Логирование** - INFO уровень с форматированием
|
||||
2. **Rate Limiting** - максимум 100 запросов в минуту
|
||||
3. **CORS** - разрешены все источники и методы
|
||||
|
||||
## Преимущества использования KrakenD
|
||||
|
||||
✅ **Высокая производительность** - написан на Go, обрабатывает тысячи RPS
|
||||
✅ **Простая конфигурация** - JSON файл, легко редактировать
|
||||
✅ **Встроенное кэширование** - улучшает скорость ответов
|
||||
✅ **Rate limiting** - защита от перегрузки
|
||||
✅ **CORS поддержка** - работа с веб-приложениями
|
||||
✅ **Логирование** - отслеживание запросов
|
||||
✅ **Health checks** - мониторинг состояния сервисов
|
||||
✅ **Гибкая маршрутизация** - поддержка параметров в URL
|
||||
|
||||
## Мониторинг и отладка
|
||||
|
||||
```bash
|
||||
# Проверить статус контейнеров
|
||||
docker-compose -f docker-compose-krakend.yaml ps
|
||||
|
||||
# Просмотреть логи Gateway
|
||||
docker-compose -f docker-compose-krakend.yaml logs api-gateway
|
||||
|
||||
# Подключиться к контейнеру Gateway
|
||||
docker-compose -f docker-compose-krakend.yaml exec api-gateway /bin/sh
|
||||
|
||||
# Проверить подключение Gateway к Service 1
|
||||
docker-compose -f docker-compose-krakend.yaml exec api-gateway curl http://service-1:8001/health
|
||||
|
||||
# Проверить подключение Gateway к Service 2
|
||||
docker-compose -f docker-compose-krakend.yaml exec api-gateway curl http://service-2:8002/health
|
||||
```
|
||||
|
||||
## Требования
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- Python 3.11+ (для локального запуска тестов)
|
||||
- curl или PostMan для тестирования API
|
||||
|
||||
## Лицензия
|
||||
|
||||
MIT
|
||||
+28
-2
@@ -1,5 +1,3 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Service 1 - User Service (порт 8001)
|
||||
service-1:
|
||||
@@ -51,6 +49,34 @@ services:
|
||||
service.name: "order-service"
|
||||
service.port: "8002"
|
||||
|
||||
# KrakenD API Gateway (порт 8000)
|
||||
api-gateway:
|
||||
image: devopsfaith/krakend:latest
|
||||
container_name: krakend-gateway
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./krakend-config.json:/etc/krakend/configuration.json
|
||||
environment:
|
||||
- KRAKEND_LOG_LEVEL=INFO
|
||||
networks:
|
||||
- microservices-network
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- service-1
|
||||
- service-2
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
command: ["run", "-c", "/etc/krakend/configuration.json", "-d"]
|
||||
labels:
|
||||
service.type: "gateway"
|
||||
service.name: "krakend-gateway"
|
||||
service.port: "8000"
|
||||
|
||||
networks:
|
||||
microservices-network:
|
||||
driver: bridge
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "https://www.krakend.io/schema/v2.12/krakend.json",
|
||||
"version": 3,
|
||||
"name": "KrakenD API Gateway",
|
||||
"timeout": "3s",
|
||||
"cache_ttl": "300s",
|
||||
"output_encoding": "json",
|
||||
"port": 8000,
|
||||
"endpoints": [
|
||||
{
|
||||
"endpoint": "/health",
|
||||
"method": "GET",
|
||||
"backend": [
|
||||
{
|
||||
"url_pattern": "/health",
|
||||
"method": "GET",
|
||||
"host": ["service-1:8001"],
|
||||
"mapping": {
|
||||
"status": "user-service-health"
|
||||
},
|
||||
"deny": [
|
||||
"service"
|
||||
]
|
||||
},
|
||||
{
|
||||
"url_pattern": "/health",
|
||||
"method": "GET",
|
||||
"host": ["service-2:8002"],
|
||||
"mapping": {
|
||||
"status": "order-service-health"
|
||||
},
|
||||
"deny": [
|
||||
"service"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"id": "95f5d4ab-abf8-4892-a888-2f1fcc80052b",
|
||||
"name": "Globals",
|
||||
"values": [],
|
||||
"_postman_variable_scope": "globals",
|
||||
"_postman_exported_at": "2026-01-05T18:54:22.002Z"
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
"""
|
||||
Первый микросервис - Service 1
|
||||
Предоставляет API для управления пользователями
|
||||
"""
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
import logging
|
||||
|
||||
app = FastAPI(
|
||||
title="Service 1 - User Service",
|
||||
description="Микросервис для управления пользователями",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# Логирование
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Модели данных
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
email: str
|
||||
age: Optional[int] = None
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
name: str
|
||||
email: str
|
||||
age: Optional[int] = None
|
||||
|
||||
# Имитация базы данных
|
||||
users_db = {
|
||||
1: {"id": 1, "name": "Иван Петров", "email": "ivan@example.com", "age": 28},
|
||||
2: {"id": 2, "name": "Мария Сидорова", "email": "maria@example.com", "age": 25},
|
||||
}
|
||||
|
||||
next_user_id = 3
|
||||
|
||||
# Маршруты
|
||||
@app.get("/", tags=["Health"])
|
||||
async def root():
|
||||
"""Проверка работоспособности Service 1"""
|
||||
logger.info("Health check для Service 1")
|
||||
return {
|
||||
"service": "Service 1 - User Service",
|
||||
"status": "operational",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
@app.get("/health", tags=["Health"])
|
||||
async def health_check():
|
||||
"""Health check endpoint"""
|
||||
return {"status": "healthy", "service": "user-service"}
|
||||
|
||||
@app.get("/users", response_model=List[User], tags=["Users"])
|
||||
async def list_users(skip: int = 0, limit: int = 10):
|
||||
"""Получить список всех пользователей"""
|
||||
logger.info(f"Получение списка пользователей (skip={skip}, limit={limit})")
|
||||
users_list = list(users_db.values())
|
||||
return users_list[skip:skip + limit]
|
||||
|
||||
@app.get("/users/{user_id}", response_model=User, tags=["Users"])
|
||||
async def get_user(user_id: int):
|
||||
"""Получить пользователя по ID"""
|
||||
logger.info(f"Получение пользователя с ID: {user_id}")
|
||||
if user_id not in users_db:
|
||||
logger.warning(f"Пользователь с ID {user_id} не найден")
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
return users_db[user_id]
|
||||
|
||||
@app.post("/users", response_model=User, tags=["Users"])
|
||||
async def create_user(user: UserCreate):
|
||||
"""Создать нового пользователя"""
|
||||
global next_user_id
|
||||
logger.info(f"Создание нового пользователя: {user.name}")
|
||||
|
||||
new_user = {
|
||||
"id": next_user_id,
|
||||
"name": user.name,
|
||||
"email": user.email,
|
||||
"age": user.age
|
||||
}
|
||||
users_db[next_user_id] = new_user
|
||||
next_user_id += 1
|
||||
|
||||
logger.info(f"Пользователь создан с ID: {new_user['id']}")
|
||||
return new_user
|
||||
|
||||
@app.put("/users/{user_id}", response_model=User, tags=["Users"])
|
||||
async def update_user(user_id: int, user: UserCreate):
|
||||
"""Обновить пользователя"""
|
||||
logger.info(f"Обновление пользователя с ID: {user_id}")
|
||||
if user_id not in users_db:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
updated_user = {
|
||||
"id": user_id,
|
||||
"name": user.name,
|
||||
"email": user.email,
|
||||
"age": user.age
|
||||
}
|
||||
users_db[user_id] = updated_user
|
||||
return updated_user
|
||||
|
||||
@app.delete("/users/{user_id}", tags=["Users"])
|
||||
async def delete_user(user_id: int):
|
||||
"""Удалить пользователя"""
|
||||
logger.info(f"Удаление пользователя с ID: {user_id}")
|
||||
if user_id not in users_db:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
del users_db[user_id]
|
||||
return {"message": f"Пользователь {user_id} удален"}
|
||||
|
||||
@app.get("/stats", tags=["Stats"])
|
||||
async def get_stats():
|
||||
"""Получить статистику по пользователям"""
|
||||
logger.info("Получение статистики")
|
||||
return {
|
||||
"total_users": len(users_db),
|
||||
"service": "user-service",
|
||||
"endpoint": "/users"
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8001)
|
||||
+5
-3
@@ -2,12 +2,14 @@
|
||||
Второй микросервис - Service 2
|
||||
Предоставляет API для управления заказами и продуктами
|
||||
"""
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI(
|
||||
title="Service 2 - Order Service",
|
||||
description="Микросервис для управления заказами и продуктами",
|
||||
@@ -78,7 +80,7 @@ async def root():
|
||||
@app.get("/health", tags=["Health"])
|
||||
async def health_check():
|
||||
"""Health check endpoint"""
|
||||
return {"status": "healthy", "service": "order-service"}
|
||||
return {"status": "healthy", "service": "order-service", "random-info": "yep"}
|
||||
|
||||
# Endpoints для продуктов
|
||||
@app.get("/products", response_model=List[Product], tags=["Products"])
|
||||
|
||||
Reference in New Issue
Block a user