【HTTP/1 JSON API 死す】(gRPC vs HTTP/1 with JSON) マイクロサービス化のすゝめ ②

## はじめに

おはようございます！
ヨーロッパの方も、今お昼ごはんを食べてる方もおはようございます！

記事タイトルをキャッチーにしてみたんですけど、釣りとかじゃないんで釣りとかじゃないんで！

本記事はマイクロサービス化のすゝめ第二章となり、前回のマイクロサービスについて紹介した記事は[こちら](https://qiita.com/taisei_otsuka/items/edc4c89bf62829d81773)となります。

今回はマイクロサービス化に伴ってgRPCを導入すべきかどうかについて語りたいと思います。
結論を先に書いておくと「導入したほうが良い」となります。

## gRPCとは何者か
まず、gRPCの正式名称から紐解いていきましょう。
正式名称は「gRPC Remote Procedure Calls」です。
再帰的頭字語が使用されていますが、そこは注目すべき点ではありません。
Callsと複数形になっていますが、**要はRPC(Remote Procedure Call)と呼ばれる昔からあるプログラムの実行手法なのです**。
その中の種類の一つとしてgRPCが誕生した、ということです。


## RPC(リモートプロシージャコール)について
プログラミングでの関数呼び出しを、同一のサーバ内ではなく、別のアドレス(サーバ)に対して行うものを指しています。

一言で言うと「別サーバで動作している関数を、呼び出す」というプログラム実行方法を指しています。

## 大体のAPIがRPC？

RPCはIDL(インタフェース記述言語)についてや、クライアントとサーバの関数はインターフェースが同一でないといけないと語られることが多く、WEB APIもRPCなのかと問われればそれは違うという回答になります。

誰でも聞いたことあるRPCの例を上げると「SOAP」等があります。

## gRPCは他のRPCやAPIと何が違うのか
gRPCの最大の特徴は**トランスポート・プロトコルにHTTP/2が採用されている**という点です。

## HTTP/2のすんごいところ

まず、HTTP/2が誕生した理由ですがそれは「通信の高速化」です。
HTTP/2がある世界ではどう高速化が行われるか、その特徴を紹介します。

### ストリームの多重化

まず、よく使われるAPIのトランスポート・プロトコルとしてHTTP/1が挙げられると思いますが、これには大きな欠点があります。

それは、**1つのリクエストが完了するまで、次のリクエストを送れない**ことです。

このHTTP/1とHTTP/2の比較サイトを御覧ください。
https://http2.akamai.com/demo
通信環境が良いと明確に速度比較がしづらいですが、スマホの回線などでアクセスして頂ければその表示速度は5~10倍ほどの差がでます。

これはHTTP/2は並列リクエスト・レスポンスをサポートしているため、前回リクエストのレスポンスを待つことなくリクエストを送れるため高速なのです。
また、ストリームの多重化が行えることにより並列のリクエスト・レスポンスを1TCPコネクション上で展開出来るため通信リソースの節約にもなります。

### ヘッダー圧縮
HTTP/2はヘッダーのサイズを圧縮してデータ通信を行います。(通信データの軽量化)
イメージとしてはgzip等で圧縮されていると思ってください。
(※ 正確な圧縮技術は[HPACK](https://httpwg.org/specs/rfc7541.html))

### バイナリフレームの採用
HTTP/1はテキストプロトコルが採用されていましたが、HTTP/2ではバイナリプロトコルが採用されています。

この部分の説明はよく誤解を生みますが、基本的にサーバはバイナリしか解釈出来ません。
では、HTTP/1ではテキストデータをサーバはどうやって解釈しているかというと、通信中にバイナリエンコードがかかっています。

HTTP/2ではサーバ間のデータのやり取りをバイナリのみでしか行わないため、テキストからバイナリにエンコードを行うリソースが節約され高速にやりとりが可能となります。

### その他の特徴
自動的な通信の優先度付けや、キャッシュを使用したサーバープッシュ等他にも特徴が存在しますが今回は割愛します。

## gRPCは速いの？
正確に言いましょう。
gRPCが速いんじゃない！HTTP/2が速いんだ！
HTTP/2の高速化のメリットを内包し、RPCとしてそれを実現しているgRPC自体はもちろん凄いです。

## gRPCの特徴

### 多様なリクエスト・レスポンス方式

gRPCは以下のリクエスト・レスポンス方式を採用できます。

- Unary RPC (1リクエスト・1レスポンス方式)
- **Server streaming** RPC (1リクエスト・複数レスポンス方式)
- **Client streaming** RPC (複数同時リクエスト・1レスポンス方式)
- Bidirectional streaming RPC (複数同時リクエスト・複数レスポンス方式)

引用元: https://grpc.io/docs/what-is-grpc/core-concepts/

**HTTP/2のストリームの多重化**を説明しているので、なぜこれが実現出来るかは理解いただけるかと思います。


### gPRCのIDLはProtocol Buffers
RPCではしばしばIDL(インターフェース定義言語)が使用されます。
(Java RMIのようなJavaのみのRPC等は除く)

gRPCのIDLは**Protocol Buffers**と呼ばれます。
拡張子は```.proto ```で、OpenAPIでいう[OpenAPI Specification](https://swagger.io/specification/)をイメージしてもらえるとわかりやすいです。

以下、公式のQuick startから拝借したものです。

``` proto
// サービス定義
service HelloWorld {
  // RPC 関数名の定義
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// リクエスト・インターフェイス
message HelloRequest {
  // 1を代入しているのではなく、識別IDを割り振っている (1~536,870,911までの整数なら何でも良い)
  string name = 1;
}

// レスポンス・インターフェイス
message HelloReply {
  string message = 1;
}
```

### コード生成ツールはprotoc (Protocol Buffers Compiler)
RPCでは、しばしばIDLからコンパイラを用いてメソッド呼び出し用のコード生成を行います。
gRPCではprotocと呼ばれるツールを使用します。

以下、は公式から拝借した例です。

``` shell
protoc -I=$SRC_DIR (使用する.protoが配置されているdir) \
  --go_out=$DST_DIR (自動生成されるコードを配置する場所) \
  $SRC_DIR/addressbook.proto (使用する.proto fileの指定)
```

生成されたコードを介して、データをバイナリへの変換及びRPCの通信を行います。
(データのシリアライズ・デシリアライズ)

### OpenAPIとgRPCの類似性

IDLを使用するという点もサーバ・クライアントコードを自動生成するという点もOpenAPIとgRPC(RPC)は非常に類似していることがわかると思います。
なのでOpenAPIのメリットを理解し使用している方は、gRPC(RPC)を利用するメリットがスムーズに理解いただけるかと思います。

また、**手動作成APIドキュメントと実際のソースコードが乖離する**というのはもはやどうやっても避けられない問題かと思いますが、OpenAPI同様gRPCはIDLをベースにコード生成・使用するため**IDL自体がAPIドキュメントとしてチーム内で利用することが可能**です。
これはチーム開発において大きなメリットとなります。

### gRPCはブラウザから呼べない
なので仮にサーバからhogehoge12345.com:3000でgRPCのAPサーバを立ち上げたとしても、
ブラウザにURLを入力して結果を表示したり、jsからAPIを叩くことは不可能です。

※ 実はgRPC-Webを使用すれば可能です。詳しくは[こちらの記事](https://qiita.com/taisei_otsuka/items/2a736fc54c3cc98c108c)を見てください。
※ HTTP/2自体はブラウザ対応しています。

## gRPCはマイクロサービスで取り入れるべきか
取り入れるべきだと私は考えます。
そもそもマイクロサービスはDBもAPサーバも分割するのが前提となります。
そうなると、サービスが増えるたびにサーバ間のコネクション数が増大することは目に見えています。

なので、将来的にサービス間の連携速度がボトルネックになることが予想されるため、先んじて通信速度の速いHTTP/2を採用するのは自然な流れだと思っています。

## 最後に
2章にわたって記事を書くことがなかったので大分疲れました(´；ω；｀)
あと、HTTP/1 JSON APIは今後10年以上は死なないよ、とだけ言わせてくださいw

ここまで読んでくれた貴方にSpecial Thanksを☆

## 採用PR

大規模サイトのでマイクロサービス構築に興味がある、もしくはチャレンジしてみたいといったお気持ちの方は是非是非一緒に働きましょう！

もちろん、マイクロサービスに興味がない方でも問題ないのでご気軽に応募ください♪

https://hrmos.co/pages/eisys/jobs/0AAA002

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307359/2000f749-3e82-7a47-b1c4-4444e237f79c.png" width=45%>