выделили мы сервис Order, и решили подвести его под RESTful. Что используется для обновления данных? Правильно, PUT. За что отвечает сервис Order? Что мы можем обновить? Например, статус заказа, и, например, мы можем отредактировать заказ. Можно сделать одну ручку, которая будет обновлять заказ, в рамках который мы сможем обновить любые поля, например, только статус. Но помимо самих заказов у сервиса Order может быть ещё несколько сущностей, связанных с заказами, которые тоже нужно будет обновлять. Таким образом PUT потеряет идемпотентность, и придётся делать несколько ручек на обновление, что уже не будет накладываться на RESTful.
Резюмируя тему REST API, приводятся основные преимущества и недостатки REST:
* Он простой и привычный
* API на основе HTTP достаточно просто тестировать
* Он имеет встроенную поддержку взаимодействия вида запрос-ответ
* Протокол HTTP дружественнен к брандмауэрам
* Он не нуждается в промежуточном брокере, что упрощает систему
И недостатки:
* Он поддерживает только 1 стиль - запрос-ответ
* Степень доступности снижена. Поскольку клиент и сервис взаимодействует между собой напрямую, без промежуточного звена для буферизации сообщений, они оба должны работать на протяжении всего обмена данными
* Клиенты должны знать местонахождение (URL) сервиса
* Извлечение нескольких ресурсов за один запрос связано с определёнными трудностями
* Иногда непросто привязать несколько операций обновления к HTTP-командам
Несмотря на недостатки, REST считается де-факто стандартом для построения API. Но, есть и множество альтернатив, например - gRPC, которую мы дальше и рассмотрм.
gRPC - двоичный протокол на основе сообщений, для написания многоязычных клиентов и серверов. Проектирование сервиса должно начинаться с его API. В gRPC API описывается с помощью языка IDL на основе Protocol Buffers - многоязычного механизма сериализации структурированных данных от Google. Компилятор Protocol Buffer генерирует клиентские заглушки и серверные каркасы, и поддерживает разные языки. Клиенты и серверы обмениваются сообщениями в формате Protocol Buffers используя HTTP/2.
gRPC API состоит из определений сервисов и сообщений вида "запрос/ответ". Определение сервиса - что-то вроде интерфейса в ООП языках: набор строго типизированных методов. Помимо стандартного флоу вида запрос-ответ, gRPC поддерживает поточный вызов процедур: сервер может вернуть клиенту поток сообщений, и клиент может отправить на сервер поток сообщений.
Ниже приведу пример gRPC API для сервиса Order, описывающего несколько методов, включая createOrder():
service OrderService {
rpc createOrder(CreateOrderRequest) returns (CreateOrderReply) {}
rpc cancelOrder(CancelOrderRequest) returns (CancelOrderReply) {}
rpc reviseOrder(ReviseOrderRequest) returns (ReviseOrderReply) {}
}
message CreateOrderRequest {
int64 restaurantId = 1;
int64 consumerId = 2;
repeated LineItem lineItem = 3;
}
message LineItem {
string menuItemId = 1;
int32 quantity = 2;
}
message CreateOrderReply {
int64 orderId = 1;
}
Преимущества протокола gRPC:
* Он позволяет легко спроектировать API с богатым набором операций
* Он имеет эффективный компактный механизм IPC, что особенно явно проявляется при обмене крупными сообщениями
* Поддержка двунаправленных потоков
Недостатки:
* Для JS, например, процесс описания API на gRPC более трудоёмок, нежели для REST из-за особенностей типизации
* Старые брандмауэры не поддерживают HTTP/2