← Назад к вопросам
Что использовалось вместо 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
Лучше всего выбирать подход в зависимости от конкретных требований проекта, а не следовать модному тренду.