LoginSignup
8
2

More than 3 years have passed since last update.

gRPCの通信をgzip圧縮する(go言語)

Posted at

サーバ・クライアント間でデータをやり取りするとき、ネットワーク帯域がボトルネックになるケースは多いです。
gRPCはProtocol Buffersによってデータのシリアライズをしており変数名などはタグ化されるし、数値型はちゃんと数値データとして送信されるので、JSONに比べて通信量的に有利です。
しかし所詮はその程度なので、大量のデータをやり取りすることを考えるときちんとデータを圧縮するべきです。

go言語のgRPCパッケージにはgzip圧縮用のライブラリが組み込まれており、少ないコードで通信をgzip圧縮できます。

サーバ側

server.go
省略
import (
    "google.golang.org/grpc"
    _ "google.golang.org/grpc/encoding/gzip"
    
省略

"google.golang.org/grpc/encoding/gzip"をアンダースコア付でインポートする。それだけです。
こうすると、起動時にinit関数が呼ばれて、gzip圧縮ができるサーバとして動作します。

クライアント側

client.go
省略
import (
    "google.golang.org/grpc"
    "google.golang.org/grpc/encoding/gzip"
    

省略

func main() {
    conn, err := grpc.Dial("localhost:19003", grpc.WithInsecure())
    if err != nil {
        log.Fatal("client connection error:", err)
    }
    defer conn.Close()
    client := hogegrpc.NewHogegrpcClient(conn)
    message := &hogegrpc.GetDataMessage{TargetCode: 0}
    response, err = client.GetData(context.TODO(), message, grpc.UseCompressor(gzip.Name))
省略

サーバ側と同じくgzip圧縮のパッケージをimportします。こちらはアンダースコア無し。
そしてgRPCで実行する関数の可変引数部分に、grpc.UseCompressorを指定してあげます。
こうすると、クライアントからサーバに接続する時に「gzip圧縮できるよ」という情報が渡り、gzip圧縮してデータのやりとりができます。

見ての通り関数呼び出しごとに指定するため、文字列等の圧縮が効きやすいデータはgzip圧縮して通信、メディア等の圧縮済みのデータをやりとりするなら無圧縮、という使い分けが容易です。

性能試験

適当なオープンデータを垂れ流すgRPCサーバを立てて試験しました。
内容は数値半分、文字列半分。1レコードあたり400byte前後のデータになります。

送信するパターンは1レコードずつ送信・全レコード(4,900件)一括送信の2つ。
試験環境はサーバ/クライアントを同一マシン上に置いたパターンと、別マシン上に置いて無線LANで通信させるパターンで測定します。

時間は関数呼び出しの前後で取得し、「クライアントから要求を出して、クライアント上でデータのデシリアライズが終わるまで」を測定します。

1レコードずつ送信

1回400byte前後のデータをやりとりします。

通信先 無圧縮 gzip圧縮
localhost 0.10 ms 0.50 ms
無線LAN上 1.87 ms 2.20 ms

えー、大々的に言ったわりにgzip圧縮は遅い
圧縮・展開にかかるオーバーヘッドがかなり大きいことと、たかが400byte程度のペイロードでは1パケットに収まってしまうので、圧縮しようがしまいが通信量が変わらないことが原因でしょう。

全レコード一気に送信

1回1,900Kbyte程度のデータをやりとりします。

通信先 無圧縮 gzip圧縮
localhost 15.81 ms 30.08 ms
無線LAN上 190.06 ms 56.51 ms

通信量が増えるとgzip圧縮の効果が見えてきます。
localhost上ではさすがにネットワーク帯域がボトルネックにならないので圧縮するだけ不利ですが、無線LAN上のマシンに対しては3~4倍近い性能差が出せています。
ちなみにスループットは100Mbps超ぐらい出ており、明らかに無線LANの帯域がボトルネックです。

まとめ

以下を満たす条件では、gzip圧縮を検討する価値があります。

  • ネットワーク帯域がボトルネックだ
  • 通信するデータが文字列や数値など、圧縮効果が見込める
  • 一度に転送するデータが1パケットに収まらない

gRPCがなんだか遅いな、っていう人は試してみるといいんじゃないでしょうか。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2