← Назад к вопросам

Что использовалось вместо REST на проектах?

3.0 Senior🔥 121 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Альтернативы REST на проектах

Н REST является стандартом, но на разных проектах я использовал и другие подходы. Разберу когда и почему выбирают альтернативы REST.

1. GraphQL

Когда использовал GraphQL

# GraphQL часто использовал на фронтенд-интенсивных проектах
# где нужна гибкость в выборке данных

from ariadne import QueryType, MutationType, make_executable_schema
from ariadic.graphql import graphql_sync

type_defs = """
    type Query {
        user(id: ID!): User
        users(limit: Int): [User!]!
    }
    
    type User {
        id: ID!
        name: String!
        email: String!
        posts: [Post!]!
    }
    
    type Post {
        id: ID!
        title: String!
        content: String!
    }
"""

query_type = QueryType()

@query_type.field("user")
def resolve_user(obj, info, id):
    # Клиент выбирает ровно те поля, которые нужны
    # Нет over-fetching и under-fetching
    return get_user(id)

@query_type.field("users")
def resolve_users(obj, info, limit=10):
    return get_users(limit)

schema = make_executable_schema(type_defs, query_type)

# Клиент может запросить:
# query {
#   user(id: "123") {
#     name
#     email
#   }
# }
# 
# И получит РОВНО эти поля, ничего лишнего

Преимущества GraphQL

advantages_graphql = {
    "flexibility": "Клиент выбирает какие поля нужны",
    "no_overfetching": "Не получаем лишние данные",
    "no_underfetching": "Не нужно несколько запросов",
    "introspection": "Самодокументируемое API",
    "type_safety": "Строгая типизация",
    "real_time": "Встроена поддержка subscription для real-time"
}

Когда НЕ использовать GraphQL

# Для простых CRUD операций GraphQL часто оверинжиниринг
# Лучше простой REST

not_suitable_for = {
    "simple_apis": "Если только 3-4 endpoint'а",
    "file_uploads": "Сложнее чем в REST",
    "performance_critical": "Может быть медленнее",
    "team_inexperienced": "Нужен опыт работы с GraphQL",
    "caching": "Сложнее кэшировать"
}

2. gRPC

Когда использовал gRPC

# gRPC использовал для микросервисов where performance matters

# service.proto
syntax = "proto3";

package user_service;

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (stream User);
  rpc CreateUser (CreateUserRequest) returns (User);
}

message User {
  int64 id = 1;
  string name = 2;
  string email = 3;
}

message GetUserRequest {
  int64 id = 1;
}

# Python реализация
import grpc
from concurrent import futures
import user_service_pb2
import user_service_pb2_grpc

class UserServiceImpl(user_service_pb2_grpc.UserServiceServicer):
    def GetUser(self, request, context):
        user = db.query(User).filter(User.id == request.id).first()
        if not user:
            context.abort(grpc.StatusCode.NOT_FOUND, "User not found")
        return user_service_pb2.User(
            id=user.id,
            name=user.name,
            email=user.email
        )
    
    def ListUsers(self, request, context):
        users = db.query(User).limit(request.limit).all()
        for user in users:
            yield user_service_pb2.User(
                id=user.id,
                name=user.name,
                email=user.email
            )

# Запуск сервера
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_service_pb2_grpc.add_UserServiceServicer_to_server(
    UserServiceImpl(), server
)
server.add_insecure_port('[::]:50051')
server.start()

Преимущества gRPC

advantages_grpc = {
    "performance": "HTTP/2, binary protocol, очень быстро",
    "typing": "Полная типизация с .proto файлами",
    "streaming": "Встроена поддержка streaming",
    "efficiency": "Меньше размер payload",
    "microservices": "Идеально для микросервисов",
    "multiplexing": "Множественные вызовы по одному соединению"
}

Когда gRPC подойдёт

use_grpc_for = {
    "microservices": "Общение между сервисами",
    "high_throughput": "Высокая пропускная способность",
    "streaming": "Нужно много streaming операций",
    "real_time": "Real-time приложения",
    "internal_apis": "Не публичное API (нет браузерной поддержки)"
}

3. WebSocket

Когда использовал WebSocket

# WebSocket для real-time приложений

from fastapi import FastAPI, WebSocket
import asyncio

app = FastAPI()

@app.websocket("/ws/chat/{room_id}")
async def websocket_endpoint(websocket: WebSocket, room_id: str):
    await websocket.accept()
    
    try:
        while True:
            # Получить сообщение от клиента
            data = await websocket.receive_text()
            
            # Сохранить в БД
            message = Message(
                room_id=room_id,
                content=data,
                user_id=websocket.user_id
            )
            db.add(message)
            db.commit()
            
            # Отправить всем в комнате
            broadcast_to_room(room_id, {
                "type": "new_message",
                "content": data,
                "timestamp": datetime.utcnow()
            })
            
    except Exception as e:
        await websocket.close(code=1000)

Когда WebSocket подойдёт

use_websocket_for = {
    "real_time_chat": "Чат, сообщения",
    "live_notifications": "Push-уведомления",
    "collaborative_editing": "Google Docs-like приложения",
    "live_data": "Stock prices, live sports scores",
    "gaming": "Multiplayer games"
}

4. Message Queue / Event-Driven

Когда использовал message queue

# Для асинхронной обработки вместо REST

from celery import Celery
from kombu import Exchange, Queue

app = Celery('myapp')

app.conf.update(
    broker_url='amqp://guest:guest@localhost//',
    result_backend='redis://localhost:6379/0',
)

# Вместо REST endpoint, публикуем событие
@app.task(name='process_order')
def process_order(order_data):
    # Асинхронная обработка
    order = Order.create(**order_data)
    charge_payment(order)
    send_confirmation_email(order)
    return {"order_id": order.id}

# Клиент не ждёт результата
process_order.delay({
    'user_id': 123,
    'amount': 99.99
})

# Вместо:
# POST /api/v1/orders - ждём ответа

Когда event-driven подойдёт

use_event_driven_for = {
    "background_tasks": "Отправка emails, обработка файлов",
    "decoupling": "Отделить order от payment",
    "scalability": "Обработка спиков нагрузки",
    "microservices": "Коммуникация между сервисами",
    "audit_trail": "История всех событий"
}

5. RPC (Remote Procedure Call)

Когда использовал RPC

# JSON-RPC для специфичных случаев

# Запрос: 
{
    "jsonrpc": "2.0",
    "method": "withdraw",
    "params": {
        "account": "123456",
        "amount": 50
    },
    "id": "1"
}

# Ответ:
{
    "jsonrpc": "2.0",
    "result": {
        "account": "123456",
        "balance": 950
    },
    "id": "1"
}

Сравнение подходов

comparison = {
    "REST": {
        "pros": ["Simple", "Standard", "Cacheable", "Stateless"],
        "cons": ["Over/under-fetching", "Multiple requests"],
        "use_case": "Most APIs, public APIs"
    },
    
    "GraphQL": {
        "pros": ["Flexible", "Single request", "Type-safe"],
        "cons": ["Complex", "Hard to cache", "Learning curve"],
        "use_case": "Complex queries, mobile clients"
    },
    
    "gRPC": {
        "pros": ["Fast", "Streaming", "Type-safe"],
        "cons": ["Binary", "No browser", "Learning curve"],
        "use_case": "Microservices, high performance"
    },
    
    "WebSocket": {
        "pros": ["Real-time", "Bidirectional"],
        "cons": ["Stateful", "Hard to scale"],
        "use_case": "Chat, notifications, live updates"
    },
    
    "Message Queue": {
        "pros": ["Async", "Decoupled", "Reliable"],
        "cons": ["Complexity", "Eventual consistency"],
        "use_case": "Background tasks, microservices"
    }
}

Мой опыт выбора

decision_tree = {
    "Публичное API": "REST (KISS)",
    "Гибкие запросы": "GraphQL",
    "Микросервисы": {
        "Высокая производительность": "gRPC",
        "Async обработка": "Message Queue",
        "Simple communication": "REST"
    },
    "Real-time": {
        "Push notifications": "WebSocket",
        "Permanent connection": "WebSocket",
        "Periodic updates": "REST polling"
    },
    "Background jobs": "Message Queue / Celery"
}

Практический пример: комбинированный подход

# На боольшом проекте часто комбинируем:

architecture = {
    "client_api": "REST (или GraphQL)",
    "internal_services": "gRPC",
    "async_processing": "Message Queue (RabbitMQ)",
    "real_time": "WebSocket",
    "mobile_clients": "REST (due to simplicity)"
}

# Пример flow:
# 1. Клиент → REST API → Get order
# 2. API → gRPC → Internal payment service
# 3. Payment service → Message Queue → Notification service
# 4. WebSocket → Real-time notification to user

Вывод

Нет универсального решения:

  • REST — для большинства случаев (KISS)
  • GraphQL — когда нужна гибкость
  • gRPC — для performance в микросервисах
  • WebSocket — для real-time
  • Message Queue — для async decoupling

Лучше всего выбирать подход в зависимости от конкретных требований проекта, а не следовать модному тренду.

Что использовалось вместо REST на проектах? | PrepBro