---
# System prepended metadata

title: Ch 08. RPC 與 Query-Based API 設計
tags: [Book, Web API 設計原則：API與微服務傳遞價值之道]

---

# Ch 08. RPC 與 Query-Based API 設計

Restful 之外最常被用到的 API 風格是 RPC (Remote Procedure Call, 遠端程序呼叫) 及 Query-Based API (查詢式 API)

## 什麼是 RPC API

RPC 的概念是執行遠端的程式碼，Server 給 Client 一個清單，讓 Client 知道 Server 有這些程式可以跑，以及每個程式各自的 Request 及 Response 結構。
RPC 架構下，Client 及 Server 的程式是緊密綁定的，一旦 Server 改變，Client 也會跟著改變
:::info
原本以為 Client / Server 是緊密綁定這件事蠻唬爛的，但搜尋了一下文件發現，在 .net 的範例中，可以透過 grpc tool 直接產生一個 cs file，後端需要透過繼承這個 cs 來實作這個 gRPC 的 endpoint
不過感覺跟 Client / Server 還是感覺可以分開實作，他頂多跟 Restful 一樣，可能異動 Server 後，Client 也要跟著異動
:::

#### gRPC vs Restful API
![](https://i.imgur.com/DVhvobJ.png)

Ref. https://pjchender.dev/golang/grpc-getting-started/

### gRPC 

gRPC 是 Google 發起的協議，Kubernetes 內部也是透過 gRPC 來做資訊的交換。gRPC 用 HTTP/2 作為底層的通訊協議，並且使用 Protocol Buffers (ProtoBuf) 來當作 Request 及 Response 的資料格式，並且利用 HTTP/2 的雙向串流特性來實現 Client/Server 的互動

#### gRPC 資料交換機制
![](https://i.imgur.com/fPR3tXc.png)

通常 ProtoBuf 的格式如下：

```protobuf
 syntax = "proto3";

 import "google/protobuf/timestamp.proto";
 option csharp_namespace = "grpc_chat";

 package chat;

 service Chatroom {
   rpc Join(stream SpeakRequest) returns (stream BroadcastMessage);
 }

 message SpeakRequest {
   string uid = 1;
   string name = 2;
   string message = 3;
 }

 message BroadcastMessage {
   string speaker = 1;
   google.protobuf.Timestamp time = 2;
   string message = 3;
 }
```

### RPC 優缺點

優點
* RPC 效能較好
* 因為遵守 ProtoBuf 定義的格式來開發，因此不用特別思考 Endpoint 要如何設計，靠工具 Generate 出來後，直接實作內容就好了

缺點
* 格式難以閱讀
* 無法指定媒體類型 (media type)
* 如果 Client 是瀏覽器的話，需要安裝其他的套件並強制使用他的指定的驗證機制才能與 API Endpont 進行互動 (無感)

### RPC API 規格

一樣先定義出來 Request 及 Response，並且照著 ProtoBuf 風格填寫

![](https://i.imgur.com/scFu7ww.png)

最後就可以產生出一份 ProtoBuf 的文件

![](https://i.imgur.com/VBKtwgh.png)

## 什麼是 Query-Based API

Query-Based API 是以查詢為基礎的 API，讓 Client 可以自己決定要如何查詢資料，並且自己決定要拿那些資料，而且也有分頁及過濾的能力
Query-Based API 也可以一次把跟該資源有相關的資料一次性取回來，把他的父子資源都一起取回來，因此可以省下多次的查詢往返，而目前較流行的方案是 OData 及 GraphQL

### OData
OData 是由 OASIS 管理的標準化協議，他是以 HTTP 及 Json 為基礎的 Query-Based API，跟 Restful 很接近，且也以 **"資源"** 為核心概念
通常 OData 也會實作 Hypermedia 的相關資源或連結

#### 書上提供的 OData 範例
![](https://i.imgur.com/4tV7BBo.png)

:::success
但我還是覺得 OData 不好維護，如果專案不夠大型，資料不夠多元，用 OData 會讓服務變得相對難維護
:::

### GraphQL

由 Facebook 在 2012 年開發，2015 年公開，目標是讓 Client 可以自行決定回應的粒度及資料深度
GraphQL 只有用到 Get 及 Post 而已，具體的內容以 GraphQL 的查詢語言撰寫，也可以在查詢內對服務下某些運算或邏輯

#### 書上提供的 GraphQL 範例
![](https://i.imgur.com/xg9oT8F.png)

GraphQL 可以做為既有 Rest API 的前端，並且解析完 Request 後再轉給後端的 REST API 取得資料後，在彙整回去給前端
GraphQL 在設計上是以單一 Endpoint 與 Client 互動，因此 GraphQL 也難以用到 HTTP 的既有特性

### Query-Based API 設計流程

1. 為所有資源設計圖譜結構
![](https://i.imgur.com/aGlMZxj.png)

2. 設計 Query 及 Mutation (異動) 操作
    Safe => Query
    Idempotent / Unsafe => Mutation
3. 撰寫 API 規格文件
![](https://i.imgur.com/4YzKs3a.png)



###### tags: `Web API 設計原則：API與微服務傳遞價值之道` `Book`