yt coffee

Study hard, play harder.

gRPC-Web がプロキシを必要とする理由

  • 2019-01-25 13:30
  • gRPC

gRPC-Web のドキュメントを読むとこれと言った説明もなく唐突に Envoy が出てきて面食らいます(そもそも Envoy とはなんぞやというのは割愛)

In this example, we will use the Envoy proxy to forward the gRPC browser request to the backend server. - gRPC Basics - Web

gRPC は HTTP/2 を使いますが、最近のブラウザは HTTP/2 で通信できるのだからサポートブラウザを限定すればわざわざプロキシを立てる必要性はなさそうな気がします。にも関わらずなぜプロキシが必要なのでしょう?

ブラウザの制約

gRPC-Web のプロトコルを説明したドキュメントにヒントがありました:

decouple from HTTP/2 framing which is not, and will never, be directly exposed by browsers - grpc/PROTOCOL-WEB.md at master · grpc/grpc

つまり

  • ブラウザ上で動作する JavaScript からは HTTP/2 を完全にコントロールすることができない
  • gRPC はプロトコルの中でその JavaScript からコントロールできない機能を使っている
  • なのでプロキシが必要

ということのようです。

なぜコントロールできない

なぜブラウザで絶対にコントロールできるようにならないと言い切れるのか。その理由はブラウザというかパブリック Web での HTTP/2 の立ち位置が関係しています。

長いこと Web では HTTP/1.1 が使われてきました。なので Web サーバが HTTP/1.1 で通信できることは期待できます(というかそれが Web サーバの定義か)が、 HTTP/2 で通信できるかどうかは不明です。ブラウザは HTTP/2 で通信できればそうしますが、できない場合は HTTP/1.1 を勝手に使います。

また通信プロトコルはレイヤーアーキテクチャなので、上位に位置する Web アプリケーションが下位で使われているのが HTTP/2 なのか、あるいは HTTP/1.1 なのかを意識するべきではありません。つまり HTTP/1.1 と HTTP/2 を透過的に扱えなければならない以上、片方にしか存在しない機能を操作する API が提供されることはない、そして gRPC ではその領域に属する機能を使っているわけなのです。

Envoy 以外の選択肢

それはさておき Envoy は gRPC-Web 用のプロキシ実装の一つに過ぎません。他にもいろいろあるはずです。

で調べてみたのだけど、結局まともに使えそうなのが improbable-eng/grpc-web しか見つけることができませんでした。improbable-eng/grpc-web は Go で書かれたプロキシ実装で、 Go プログラムから標準の http.Handler をラップして使うか、 Envoy のように grpcwebproxy コマンドでプロキシを立てることができるようです。これを使えば Go で書いた gRPC サーバが直接 gRPC-Web と通信することはできそうです。

GAE で gRPC-Web 使うには

そもそもなんで gRPC-Web とプロキシについて調べていたのかというと GAE で作った gRPC サービスに gRPC-Web からアクセスしたいと思ったからなのでした。

流石に GAE の前に Envoy を立てるのは面倒なので、そもそも本当にプロキシ必要なのかよ?...必要だった。他にやり方ないのか?...improbable-eng/grpc-web を発見という次第です。というわけで GAE Go で gRPC 作ってみることにします。

参考