API 管理

API 設計: gRPC、OpenAPI、REST の概要と、それらを使用するタイミングを理解する

#api

※この投稿は米国時間 2020 年 4 月 11 日に、Google Cloud blog に投稿されたものの抄訳です。

ほとんどのソフトウェア デベロッパーがご存じだと思いますが、API 設計には RPC と REST の 2 つの主要なモデルがあります。モデルに関係なく、ほとんどのモダン API は、なんらかの方法で同じ HTTP プロトコルにマッピングすることによって実装されます。また、RPC API 設計では、RPC モデルの範囲から外れずに HTTP から 1 つまたは 2 つのアイデアを採用することが一般的になっています。これにより、API 設計者に提示されるオプションの範囲が広がりました。この投稿ではこれらのオプションについて説明し、どれを選ぶか決める際に役立つガイダンスを提供します。

gRPC は RPC API を実装するためのテクノロジーで、HTTP 2.0 をその基盤となるトランスポート プロトコルとして使用します。gRPC と HTTP は基盤となる概念モデルが正反対であることから、相互に排他的であると思われるかもしれません。gRPC はリモート プロシージャ コール(RPC)モデルに基づいており、アドレス指定可能なエンティティがプロシージャで、データはその背後に隠れています。HTTP はこの逆の方法で機能します。HTTP では、アドレス指定可能エンティティは「データ エンティティ」です(HTTP の仕様では「リソース」と呼ばれます)。システムの動作は、データ エンティティを作成、変更、削除した結果で、こうした動作はデータの背後に隠れています。

実際、Google や他の場所で作成された API の多くには、HTTP のいくつかのアイデアが興味深い方法で RPC に組み合わされています。これらの API は、HTTP と同様にエンティティ指向モデルを採用していますが、定義および実装には gRPC が使用されています。作成された API は標準の HTTP テクノロジーを使用して呼び出せます。ここでは、その仕組み、それが適している理由や、適していない状況を説明します。

まず、API で HTTP が一般的にどのように使用されるかについて詳しく見てみましょう。

API に HTTP を使用する 3 つの主要な方法

ほとんどの公開 API と多くの非公開分散 API は、トランスポートとして HTTP を使用します。少なくともその理由の一つは、組織がポート 80 と 443 で HTTP トラフィックを許可するというセキュリティ問題への対処に慣れているためです。

私としては、HTTP を使用する API のビルドには、重要かつ特徴のあるアプローチが 3 つあると考えています。次のようなアプローチです。

  1. REST

  2. gRPC(および Apache Thrift など)

  3. OpenAPI(およびその競合製品)

REST

最も使用頻度の低い API モデルは REST です。REST という単語が広く使用(あるいは乱用)されていても、この方法で設計されている API は非常に少数です。このスタイルの API の特徴的な性質は、クライアントが他の情報から URL を構築せず、サーバーから渡された URL をそのまま使用することです。ブラウザの振る舞いとしては、使用する URL を部分から組み立てることも、使用する URL のウェブサイト固有の形式を理解することもせず、サーバーから受信した現在のページで見つかった URL、または前のページからブックマークされていた URL、あるいはユーザーが入力した URL をそのままたどるだけです。ブラウザが URL を解析するのは、HTTP リクエストを送信するために必要な情報を抽出する場合のみであり、ブラウザが URL を組み立てるのは、相対 URL とベース URL から絶対 URL を形成する場合のみです。API が REST API の場合、クライアントは URL の形式を理解する必要がなく、それらの形式はクライアントに提供される API 仕様に含まれません[1]。

REST API は非常にシンプルになります。REST API と併用するための追加のテクノロジーが数多く考案されています。JSON API、ODATA、HAL、Siren、JSON Hyper-Schema などがその一例ですが、REST を使いこなすためにこれらのテクノロジーが必要という訳ではありません。

gRPC

API に HTTP を使用するための 2 番目のモデルは、gRPC で示されます。gRPC は内部で HTTP/2 を使用しますが、HTTP は API 設計者には公開されません。gRPC で生成されるスタブとスケルトンにより HTTP はクライアントとサーバーから見えません。ですから、RPC のコンセプトが HTTP にどのようにマッピングされるかを気にせず、ただ gRPC を学ぶだけで良いのです。

クライアントが gRPC API を使用する場合、次の 3 つの手順に従います。

  1. 呼び出すプロシージャを決める

  2. 使用するパラメータ値を計算する(ある場合)

  3. コード生成されたスタブを使用して呼び出しを行う

OpenAPI

おそらく、HTTP を使用する RPC API の設計で最も一般的な方法は、OpenAPI(旧称 Swagger 仕様)のような仕様言語を使用することでしょう。

OpenAPI スタイルの API の特徴的な性質は、クライアントが他の情報を集めて URL を作成することによって API を使用することです。クライアントが OpenAPI API を使用する場合、次の 3 つの手順に従います。

  1. 使用する OpenAPI URL パス テンプレートを決める

  2. 使用するパラメータ値を計算する(ある場合)

  3. パラメータ値を URL パス テンプレートに挿入し、HTTP リクエストを送信する。

このように機能する API が REST API ではないことは、すぐにわかるはずです。HTTP を使用する OpenAPI メソッドでは、クライアントは、リクエストで使用する URL の形式を詳細に知っていることと、他の情報からその形式に一致する URL を作成することが求められます。これは、REST API の機能方法とは正反対です。REST API では、クライアントは使用する URL の形式をまったく知らず、また URL を作成する必要もありません。OpenAPI でサポートされているモデルは、非常に人気で成功を収めており、API 設計者が利用できる最も重要なオプションの一つです。OpenAPI モデルが REST ではないからといって、その有用性や重要性が損なわれるわけではありません。

2 つ目に気付くことはおそらく、OpenAPI API を使用するクライアント モデルが、gRPC API を使用するクライアント モデルと非常に似ているということでしょう。gRPC クライアントは呼び出すプロシージャを選択するのに対して、OpenAPI クライアントは使用する URL パス テンプレートを選択します。パラメータ値の計算は、gRPC クライアントと OpenAPI クライアントのどちらも行います。gRPC クライアントがスタブ プロシージャを使用してパラメータをプロシージャのシグネチャと組み合わせ、呼び出しを行うのに対して、OpenAPI クライアントはパラメータ値を URL パス テンプレートに挿入し、HTTP リクエストを送信します。詳細は異なりますが、モデル全体としては非常に似ています。OpenAPI には、オプションでクライアント スタブ プロシージャをクライアントのプログラミング言語で生成して、これらの詳細を見えなくするツールも含まれているため、この 2 つのクライアント エクスペリエンスはさらに類似したものになります。

gRPC と OpenAPI のクライアント モデルが類似しているのは、OpenAPI が、HTTP リクエストへのカスタム マッピングを使用し、標準の RPC API を指定するための言語であると考えられるからとも言えます。この考えを受け入れれば、gRPC と OpenAPI はどちらも RPC インターフェース定義言語(IDL)ということになります。両者の本質的な違いは、OpenAPI がクライアントに基盤となる HTTP トランスポートの詳細を公開して、API 設計者がマッピングを制御できるようにする一方で、gRPC は事前定義されたマッピングを使用して、すべての HTTP 詳細を見えないようにすることです。

OpenAPI で使用される基本的な API モデルが古き良き RPC であるという考えを受け入れない場合でも、この両者に明らかな類似点があり、どちらも REST とは異なることは否定できません。いずれにせよ、これだけ類似点があれば、この後でより詳細に比較する十分な理由になるでしょう。

これらのアプローチにはそれぞれ利点と欠点があります。3 つすべてを詳細に説明しますので、作成したいアプリケーションに最適な方法をどのように決定するかについて、ご自分でお考えください。

簡単でわかりやすい RPC

以下は、RPC の長所を称賛する人気のブログ投稿の例です。

  createAccount(username, contact_email, password) -> account_id
addSubscription(account_id, subscription_type) -> subscription_id
sendActivationReminderEmail(account_id) -> null
cancelSubscription(subscription_id, reason, immediate=True) -> null
getAccountDetails(account_id) -> {full data tree}

このブロガーは、多くの人がこの問題に対して RPC API を定義するのは簡単だと思う一方で、HTTP を使用して同じ問題を解決する方法を見つけるのに苦労し、プロジェクトに利益をもたらすことなく多くの時間とエネルギーを浪費していると述べています。同感です。HTTP の上に API を設計することは、習得が必要なスキルだからというのが理由の一つです。また HTTP の使用には少なくとも 2 つの異なる方法があり、よく混乱するためです。では両者について説明します。

REST モデルの使用も簡単でわかりやすい

これまでに REST を使用して多くの API を設計しているため、この例を REST で表す方法も同じようにわかりやすいように思えます。私が行おうとしているのは、次のとおりです。

  POST /accounts <headers> (username, contact_email, password)> -> account_URL
POST /subscriptions <headers> (account_URL, subscription_type) -> subscription_URL
POST /activation-reminder-outbox <headers> (account_URL) -> email_URL
POST /cancellations <headers> (subscription_URL, reason, immediate=True) -> cancellaton_URL
GET {account_URL} ->  {full data tree}

username、contact_email、password、account_URL、およびクライアントから提供されるその他のデータは、リクエスト本文にある単純な JSON の名前と値のペアです。ヘッダーの内容と結果の返し方の詳細は省略しました。こうしたことは、HTTP 仕様で説明されており、実際に選択や決定を行うことはありません。

クライアントとサーバー間で双方向に渡される識別子はすべて URL です。API には、URL 以外の識別子はありません。あるリソースに別のリソースへの参照が含まれている場合は常に、その参照は他のリソースの URL を使用して表現されます。この手法はハイパーテキストまたはハイパーメディアと呼ばれます。URL をこのように使用しない API は、REST モデルを使用していないことになります。ハイパーテキストのリンクは、REST を他のモデルと区別する特徴的な機能であるためです[2]。RPC API は、あるエンティティの識別子を別のエンティティに含めることによってエンティティ間の関係も表現しますが、これらの識別子は、追加情報を必要とせずに直接使用できる URL ではありません。

REST の利点

REST の利点と言われているものは基本的に World Wide Web 自体の利点であり、安定性、均一性、普遍性などです。これについては別の場所でも文書化されており、REST に関心のある人も少ないため、ここでは詳しく説明しません。ただし例外があります。それは、HTTP/REST モデルに固有のエンティティ指向です。この機能は、gRPC や OpenAPI などの非 REST モデルの提唱者によって広く議論、採用されているため、特に関心の対象になっています。

私の経験では、エンティティ指向モデルは、単純な RPC モデルに比べると、単純かつ規則的で、理解しやすく、時間の経過とともに安定性が増します。RPC API は、システムが実行できるアクションを実装するプロシージャが次々に追加されることで、有機的に成長する傾向があります。

エンティティ指向モデルは、システムの動作を全体的に構造化するものを提供します。たとえば、私たちは誰もがオンライン ショッピングの製品や、カート、注文、アカウントなど、そのエンティティ モデルをよく知っています。その機能を RPC プロシージャのみを使用して表現した場合、製品のカタログの閲覧、カートへの追加、購入手続き、配達の追跡、返品のためのプロシージャのリストは、膨大で非構造的なものになるでしょう。

このリストはすぐに手に負えないほど長くなり、プロシージャ定義間の一貫性も保てなくなります。このリストに構造と秩序をもたらす方法の一つは、エンティティ タイプごとに一連の標準プロシージャを使用して、すべての動作をモデル化することです。HTTP は本質的にエンティティ指向ですが、RPC にエンティティ指向を追加することもできます。これについては後で説明します。エンティティ タイプによるプロシージャのグループ化も、オブジェクト指向言語の重要な考え方の一つです。

OpenAPI の使用方法

OpenAPI で、パスと呼ばれるものを定義します。OpenAPI のパスは、YAML では次のように表示されます。

  paths:
  /pets/{petId}:
    get:
      operationId: getPetById
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string

このようなパスを定義する API は、API のさまざまな場所でクライアントに {petId} の値を公開し、{petId} 値(およびその他の値)を HTTP リクエストで使用できる URL に変換するために、クライアントに適切なパス定義を使用するよう求めます。

OpenAPI でこのように ID を使用するのは、HTTP 固有のアイデアの一つであるハイパーテキスト リンクの代わりです。

OpenAPI ではこれらのパスの変数を「パラメータ」と呼び、パスと HTTP メソッドの組み合わせをオペレーションと呼びます。これは、RPC システムと同様の用語です。

OpenAPI でパラメータ付きの URL テンプレートを使用することは、HTTP へのカスタム マッピングで RPC に似たコンセプトを表現する方法と見ることができます。

OpenAPI の利点と欠点

私としては、OpenAPI にはその成功の理由である基本的な特性が 2 つあると思っています。1 つ目は、OpenAPI モデルは、ほとんどのプログラマーが使い慣れている従来の RPC モデルに似ていることです。このモデルは、プログラマーが使用するプログラミング言語のコンセプトともぴったり合致します。2 つ目の理由は、HTTP リクエストへのこうした RPC コンセプトのカスタム マッピングをプログラマーが定義できることです。この 2 番目の特性は、利点と問題の両方をもたらします。主な利点は、クライアントが標準の HTTP テクノロジーのみを使用して API にアクセスできることです。これは公開 API にとって特に重要です。API がほとんどすべてのプログラミング言語と環境からアクセスでき、その際クライアントが追加のテクノロジーを導入する必要がないことを意味するからです。欠点は、HTTP の詳細を設計するために多大な労力が必要となる可能性があることです。推奨事項と禁止事項に関するウェブ上のガイダンスをすべて確認する必要がありますが、その多くが矛盾しています。また API の消費者がこれを学習するために、さらなる努力が必要になります。

gRPC が OpenAPI より優れたオプションになる場合

OpenAPI で記述された API の設計上の課題は、URL パスと HTTP メソッドの組み合わせを定義して、「オペレーション」とその「パラメータ」を表すことです。これは、オプションが多数あるため複雑な作業になる可能性があります。これがほとんどのプロジェクトにとって時間とエネルギーの有効利用であるかどうかは不明です。このアプローチに対する不満については、前述の Pascal Chambon 氏による SOAP と REST を比較したブログ記事で熱っぽく説明されています。このブログで最初に紹介した RPC のサンプルは、そこから使わせていただいたものです。

同氏の投稿にはいくつかの誤情報と誤解が見られ、そのためこの投稿に対する反応のほとんどはその修正に力を注いでいましたが、むしろこうした誤りが、同氏の主張である「RPC に似たコンセプトを HTTP にマッピングすることを独自に設計するのはかなり複雑で難しい」を裏付けたと言えるのではないでしょうか。

Chambon 氏のブログ投稿に反応して提供されたアドバイスのほとんどで、同氏や他のほとんどの人々が慣れ親しんでいる RPC に似たモデルの代わりとして REST が推奨されていました。これは確かにオプションの一つです。この投稿の冒頭で説明した単純な REST の例は、それを行う方法を最小限にとどめたミニマリストの見解です。

Chambon 氏のもう 1 つのオプションは、基本的な RPC モデルを維持しながら、OpenAPI ではなく gRPC を使用してそれを表現するというものです。これにより、HTTP への API のカスタム マッピングを定義する複雑さがなくなります。RPC モデルは他のどの方法よりも根強い人気があり、API 設計者がどうしても RPC に似たモデルを使用するという場合は、使用可能なすべてのテクノロジーを比較検討する必要があります。

gRPC のメリット

gRPC は RPC API をインターフェース記述言語(IDL)で表現します。これは、DCE IDL や Corba IDL などの長きにわたる RPC IDL の伝統のメリットを受け継いでいます。gRPC の IDL は、URL のパス、それらのパラメータ、およびそれらで使用される HTTP メソッドを使用する OpenAPI のアプローチよりも、簡単かつ直接的な方法でリモート プロシージャを定義できます。

gRPC は HTTP/2 を内部で使用しますが、HTTP/2 を API 設計者や API ユーザーに公開しません。HTTP の上への RPC モデルの重ね方はすべて gRPC で決定されるため、自分で決める必要はありません。これらの決定は gRPC ソフトウェアと生成されたコードに組み込まれています。API 設計者とクライアントはその分苦労せずに済みます。それに対して OpenAPI では、特定の API の RPC モデルを HTTP 上でどのように表現するかを API 設計者が詳細に指定する必要があり、API のクライアントもその詳細を学習する必要があります。OpenAPI アプローチの利点として重要なことは、API クライアントが標準の HTTP ツールとテクノロジーを使用できることです。これは、多くの API 設計者にとって努力が正当化されるものです。 

作成する API で HTTP をどのように使用するかに関係なく、クライアント側のプログラミング ライブラリをさまざまな言語で作成して、プログラマーに使用してもらいたい場合がおそらくあると思います。これらのプログラミング ライブラリは、プロシージャの形をとります(プログラミング言語によっては、関数またはメソッドと呼ばれることもあります)。gRPC の最も魅力的な特長の一つは、プログラマーが効率的に使用、実行できる直感的なクライアント側プログラミング ライブラリの生成に優れていることです。OpenAPI もクライアント側のプログラミング ライブラリを生成できますが、gRPC のバージョンの方がシンプルでわかりやすいと思います。これはおそらく、gRPC の IDL に必要なのは RPC のコンセプトを表現することだけで、コンセプトの HTTP へのマッピングを同時に記述する必要がないためです。

gRPC で指定された API も、サーバー側での実装が簡単です。gRPC がフレームワーク、ライブラリ、およびコード生成を提供するため、gRPC メソッドのサーバー実装を作成する方が、標準の HTTP リクエスト ハンドラを作成して、着信リクエストを解析して適切な実装関数を呼び出すよりも簡単な場合があります。

gRPC のもう一つの特長は、優れたパフォーマンスです。gRPC は、作成と解析を効率よくこなせるバイナリ ペイロードを使用し、HTTP/2 を利用して接続を効率的に管理します。もちろん、gRPC を使用せずにバイナリ ペイロードと HTTP/2 を直接使用することもできますが、そのためにはご自身とクライアントがより多くの技術を習得する必要があります。

また gRPC では、HTTP ベースで最高の API でも HTTP プロトコル全体を実装しないという問題を回避できます。REST API と OpenAPI API を使用する場合、この問題のために API プロバイダとクライアントは特定の API がサポートする HTTP のサブセットを明確化して学習する方法を考えなければいけません。しかし gRPC では、クライアントとサーバーの両方に、完全な gRPC プロトコルを実装する特別なソフトウェアを採用することで、この問題を回避できます。私たちは、gRPC が HTTP と同じように少なくとも 25 年間そのプロトコルを安定させることができ、サーバーがアップグレードされたときにクライアントが壊れたり、クライアントがアップグレードされたときにサーバーが壊れたりしないようにしたいと考えています。

エンティティ指向モデルと RPC をどのように組み合わせるか

使用しているのが gRPC か OpenAPI かに関係なく、エンティティ指向の方法で RPC を使用するコツは、RPC メソッド定義を、各リソースタイプの標準エンティティ オペレーション(作成、取得、更新、削除(CRUD と呼ばれることもある)[3]、一覧表示)に簡単にマッピングできるもののみに制限することです。

エンティティ指向のスタイルで RPC を使用するには、通常の RPC 思考プロセスを逆にします。プロシージャ定義から始めるのではなく、リソースタイプを定義することから始めて、その後でそれらのタイプで一般的なエンティティ オペレーションと、必要だと思われる追加のオペレーションに対応する RPC メソッド定義を作成します。 

RPC をエンティティ指向のスタイルで使用するには、制約された使用パターンを人々に教えることが必要になります。実際に、このように設計された API は、エンティティ指向のコンセプトとプロシージャ指向のコンセプトが混在している場合があり、それによっていくつかの利点も損なわれています。

では、gRPC の欠点とは?

すべてのテクノロジーに欠点と制約があります。OpenAPI の欠点についてはすでに説明しました。

HTTP API の人気を支える特徴の一つは、クライアントが HTTP API を使用でき、サーバーは汎用的で広く利用可能なテクノロジーのみを使用して HTTP API を実装できる点にあります。API 呼び出しは、ブラウザに URL を入力するか、ターミナル ウィンドウまたは bash スクリプトで cURL コマンドを発行するだけで簡単に行えます。プログラマーは、基本的な HTTP ライブラリ以上のテクノロジーを使用せずに、HTTP API のアクセス、実装を行えます。それに対して gRPC では、クライアントとサーバーの両方に特別なソフトウェアが必要です。gRPC で生成されたコードは、クライアントとサーバーのビルドプロセスに組み込む必要があります。これは、特に JavaScript や Python など、ビルドプロセスが(少なくとも開発マシンで)存在しない可能性がある動的言語での作業に慣れている人にとっては、煩わしいかもしれません。Google Cloud Endpoints プロダクトを使えば、特別なソフトウェアを使用しなくても HTTP および JSON を介して gRPC API にアクセスできるので、クライアントでは多くのオプションを取り戻すことができますが、誰もが Cloud Endpoints を使用したいわけではないでしょう。同等のプロダクトを探したりビルドしたりする意欲や可能性も不透明です。

メタデータなしで REST API 全体をクロールする bot を作成するのは簡単です[4]。ブラウザまたはウェブ bot が HTML ウェブ全体をクロールできるのと同じです。これは、gRPC を使用して記述されているか OpenAPI を使用して記述されているかに関係なく、RPC スタイルの API では行えません。RPC では各エンティティ タイプに異なる API を指定しており、API ではそれを使用するためにカスタム ソフトウェアまたはメタデータを必要とするためです。実際には、汎用 API クライアントを作成できることは、便利な場合もありますが、通常は重要ではありません。

HTTP API は多くの場合、セキュリティ機能の追加、入力検証の実行、データ形式のマッピング、その他の多くの問題の解決を目的にプロキシされます。これには通常、ヘッダーの追加、削除、変更、および本文の解析と変更が必要です。プロキシは、標準ヘッダーとカスタム ヘッダーを組み合わせてこれを行います。これらの機能は通常、Apigee Edge など、従来のプログラミング スキルや gRPC を簡単に統合できるソフトウェア開発環境も不要なプロダクトを使用して実装されます。gRPC にこの種のプロキシを行うのは非常に難しいと思います。また私の知る限り、これは一般的には行われていません。

gRPC でエンティティ指向のアプローチを使用することは、ほとんどの場合、新規ビルドには有用ですが、既存の RPC API にレトロフィットするのは簡単ではないでしょう。

gRPC はコンテンツ ネゴシエーションをサポートしていません。HTTP を使用すると、クライアントは、データを送受信する形式(JSON、XML、YAML など)を選択できます。HTTP コンテンツ ネゴシエーション メカニズムは、非常にシンプルかつエレガントな方法で拡張して、最も一般的な形式の API バージョニングをサポートすることもできます。しかし gRPC を使用する場合は、API バージョニングの独自のソリューションを見つける必要があります。

gRPC では、2 つのクライアントが同じリソースを同時に更新しようとしたときのデータの損失を防ぐ標準メカニズムを定義していません。そのため、gRPC を使用する場合は、独自のメカニズムを考案する必要があります。HTTP はこの目的のために標準の Etag ヘッダーと If-Match ヘッダーを定義しています。私たちが設計するほとんどの HTTP API はこれらを使用します。

gRPC では部分的な更新を行うためのメカニズムも定義していないため、独自のメカニズムを考案する必要があります。HTTP は、部分的な更新のためのメソッド(パッチ)を定義していますが、パッチの外観や適用方法については言及していません。JSON にはこのギャップを埋める追加の IETF 標準が 2 つあります。JSON マージパッチJSON パッチです。 最初のパッチは簡単に使用できますが、特に配列の更新など、すべてのケースを処理するわけではありません。2 番目のパッチはより多くのケースを処理しますが、使用方法がより複雑です。私が最近ビルドした HTTP API のほとんどは両方の標準を実装しており、クライアントに選択させるようにしています。Kubernetes API も同様です。

まとめ

HTML ウェブで使用されているものと同じ REST ハイパーテキスト モデルを使用する API がいくつかあります。こうした API は、安定性、均一性、普遍性など、HTML ウェブの中核となる品質を継承することを目的としています。このように API を設計する方法をすでに知っている場合、または学習する意欲がある場合、これは優れたアプローチです。これは私が好きなこのアプローチです。

OpenAPI で記述された API は、RPC に似たコンセプトに基づいていますが、HTTP へのカスタム マッピングを行います。このアプローチでは、クライアントは一般的に利用可能な HTTP テクノロジーのみを使用して、作成した API にアクセスできますが、これらの API では設計のオプションが多くなるため、設計とビルドが難しくなり、学習も困難になります。

API に OpenAPI を使用することを検討している場合は、gRPC を使用して設計、実装するオプションも検討されることをおすすめします。この 2 つの基本的な API モデルは同等であり、gRPC では HTTP への独自のマッピングを考案する必要がありません。

API に gRPC を使用しているか OpenAPI を使用しているかに関係なく、エンティティ指向のスタイルで API を整理している場合、プロシージャ名を標準化している場合(たとえば、作成、取得、更新、削除などの動詞に忠実になることにより)、他の命名規則を設定している場合、REST API の利点の一部(すべてではなく)を得られます。gRPC には、他にもいくつかの独自の利点があります。gRPC の使用は、次のいずれかに該当する場合は特に推奨されます。

  • Cloud Endpoints などのプロダクトを使用することで、自分が gRPC テクノロジーを採用したという理由だけでクライアントにも同じテクノロジーの採用を無理強いしないようにする場合。
  • API は内部使用で、すべてのクライアントとサーバーのテクノロジーの選択を自分が管理している場合。

OpenAPI または REST の代わりに gRPC を採用する場合、プロキシでの API の動作を拡張または修正する機会が大きく限定されることを知っておく必要があります。特に Apigee Edge やその競合製品のような API 管理ツールを使用して実装されたものには注意が必要です。gRPC を使用する方法と場所に応じて、これが問題になる場合とならない場合があります。

ほとんどの設計上の課題と同様に、考慮すべき要因が数多くあり、トレードオフも必要です。このディスカッションで、HTTP と RPC スタイルの API が互いに一致している部分について説明できていれば幸いです。

この投稿に協力してくれた Nandan Sridhar と Marsh Gardiner に感謝します。

- By ソフトウェア デベロッパー兼 API 設計者 Martin Nally


[1] 一部の REST API では、クライアントがベース URL にクエリを追加できるようになっています。この場合、クライアントは、URL のクエリ部分でサーバーがサポートするクエリ構文を理解する必要がありますが、残りの URL の形式は知る必要はありません。一部の REST API 設計者は、クエリを URL パスにエンコードできるようにしています。この場合、クエリ URL は、以下で説明する OpenAPI スタイルの URL のように見えてきます。

[2] REST のコメンテーターの中には、REST モデルへの準拠を主張するには、JSON に HTML フォームに似たものも実装する必要があると言う人もいますが、ハイパーテキスト リンクがその API の際立った機能でなければ、それは REST ではないということには、ほぼすべての人が同意するでしょう。

[3] 完全にエンティティ指向の API でさえ、「変換」と言えるような 5 番目のオペレーションが必要になる場合があります。変換では、永続的なリソースを作成せずに、1 つのエンティティを取り込んで別のエンティティを生成します。HTTP にはこのオペレーションのための特別なメソッドがないため、「作成」と「変換」の両方に POST を使用する必要があります。取得にも POST を使用して、URL の長さの制限を回避することもあります(通常、クエリを含む URL の場合)。

[4] サーバーでの追加の作業量が適度であれば、ブラウザ自体に API 全体をクロールさせることができます。