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

Почему Rest не основной способ передачи данных?

2.0 Middle🔥 81 комментариев
#REST API и микросервисы

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

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

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

REST как не основной способ передачи данных

Это интересный вопрос. REST действительно мощный стиль, но в современной архитектуре есть сценарии, где他 не оптимален.

REST прекрасен, но имеет ограничения

REST (Representational State Transfer) хорош для:
  • CRUD операций
  • Простых синхронных запрос-ответ паттернов
  • Публичных API
  • Браузер-совместимых интеграций

НО он становится узким местом когда:

1. Высокая частота данных (Real-time)

Проблема: REST запрос для каждого обновления - излишне.

// ПЛОХО - каждые 100ms новый REST запрос
for (int i = 0; i < 1000000; i++) {
    httpClient.get("/api/data/" + i);
}

// ХОРОШО - WebSocket соединение, streaming data
webSocket.onMessage(data -> {
    process(data);
});

2. Высоконагруженные системы

Проблема: каждый REST запрос создает новое соединение, overhead на TCP/TLS handshake.

// REST: 1000 запросов = 1000 TCP соединений (или переиспользование)
// gRPC: одно долгоживущее соединение, multiplexing

// PLPGSQL запросы
stub.getUser(userId1);
stub.getUser(userId2);
stub.getUser(userId3);

3. Асинхронные события

Проблема: REST request-response паттерн не подходит для pub/sub.

// ПЛОХО - polling
while (true) {
    response = httpClient.get("/api/notifications");
    sleep(1000);
}

// ХОРОШО - message broker
kafkaConsumer.subscribe("notifications");
kafkaConsumer.onMessage(event -> handle(event));

4. Слабые сетевые каналы

Проблема: REST отправляет JSON (текст), очень неэффективно для IoT/мобильных.

// REST JSON - много overhead
{
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "active",
  "balance": 10000.50
}
// Размер: ~100 байт

// gRPC protobuf - бинарный
// Размер: ~20 байт

// Экономия bandwidth в 5 раз!

5. Строгие требования на latency

Проблема: HTTP(S) имеет overhead, REST неэффективен для микросекундных требований.

REST (HTTP):     ~10ms (на локальной сети)
gRPC:            ~1-2ms
Direct TCP:      <1ms
Shared Memory:   <0.1ms

Почему я выбираю другие подходы

1. Message Brokers (Kafka, RabbitMQ)

Когда: асинхронные события, loose coupling, масштабируемость.

// Паттерн: Publisher - Subscriber
public class OrderEventPublisher {
    @Autowired
    private KafkaTemplate<String, OrderEvent> kafkaTemplate;
    
    public void publishOrderCreated(Order order) {
        kafkaTemplate.send("orders.created", order.getId().toString(), 
            new OrderEvent(order));
    }
}

public class OrderEventConsumer {
    @KafkaListener(topics = "orders.created")
    public void handleOrderCreated(OrderEvent event) {
        // Асинхронная обработка, без блокировки издателя
    }
}

2. WebSocket (для real-time)

Когда: live updates, real-time collaboration, streaming.

@Configuration
@EnableWebSocket
public class WebSocketConfig {
    @Bean
    public WebSocketHandler liveDataHandler() {
        return new WebSocketHandler() {
            @Override
            public void afterConnectionEstablished(WebSocketSession session) {
                // Отправлять данные непрерывно
                while (true) {
                    session.sendMessage(new TextMessage(getCurrentData()));
                    Thread.sleep(100);
                }
            }
        };
    }
}

3. gRPC (для микросервисов)

Когда: service-to-service communication, высокая производительность, строгие контракты.

// service.proto
service UserService {
    rpc GetUser(UserId) returns (User);
    rpc StreamUsers(Empty) returns (stream User);
}

// Сервер
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
    @Override
    public void getUser(UserId request, StreamObserver<User> responseObserver) {
        User user = userService.findById(request.getId());
        responseObserver.onNext(user);
        responseObserver.onCompleted();
    }
}

// Клиент
UserServiceGrpc.UserServiceBlockingStub stub = 
    UserServiceGrpc.newBlockingStub(channel);
User user = stub.getUser(UserId.newBuilder().setId(123).build());

4. GraphQL (гибкие запросы)

Когда: complex data fetching, mobile clients, flexible schema.

@RestController
@RequestMapping("/graphql")
public class GraphQLController {
    @PostMapping
    public Object graphql(@RequestBody Map<String, Object> request) {
        String query = (String) request.get("query");
        // Выполнить только запрошенные поля
        return graphQLEngine.executeQuery(query);
    }
}

// Клиент запрашивает только нужное
{
  user(id: 1) {
    name
    email
    // Не запрашиваем balance если не нужно
  }
}

5. Direct TCP/UDP (для критичных по latency систем)

Когда: финтех, игры, trading systems.

public class HighPerformanceServer {
    public static void main(String[] args) throws Exception {
        ServerSocket socket = new ServerSocket(5000);
        while (true) {
            Socket client = socket.accept();
            new Thread(() -> handleClient(client)).start();
        }
    }
    
    private static void handleClient(Socket socket) {
        DataInputStream in = new DataInputStream(socket.getInputStream());
        long price = in.readLong();  // Прямое бинарное
        // Минимум overhead
    }
}

Мой подход к выбору

Если нужно:
├─ CRUD + веб UI          → REST + JSON
├─ Real-time updates      → WebSocket
├─ Микросервисы           → gRPC
├─ Асинхронные события    → Message Broker
├─ Гибкие запросы         → GraphQL
├─ Критично по latency    → Direct TCP/Binary
└─ Публичный API          → REST (OpenAPI)

Вывод

REST - это хороший стандарт для типовых веб-задач, но не серебряная пуля. В современных системах нужно выбирать способ передачи данных в зависимости от:

  • Паттерна взаимодействия (sync/async)
  • Требований к latency (миллисекунды или секунды)
  • Частоты данных (редкие операции или streaming)
  • Пропускной способности (сетевые ограничения)

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