3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gRPCの通信速度を計ってみた

Last updated at Posted at 2020-09-03

Writer:       Do Nguyen Thanh
Translator: Yosuke Okusa
Director:    Yosuke Okusa
First Post:  2020-09-03

通信の話

クライアントからサーバーへ、またはインスタンスからインスタンスへの通信には、HTTPリクエストのREST APIを使うのが一般的です。
しかし、ストリーミングデータ伝送など、低遅延かつ高速な通信が要求されるプロジェクトでは、新しいRPCフレームワーク「gRPC API」が使われる傾向にあります。

gRPCとは?

そもそも gRPC API とは、Googleのプロトコルバッファー(「Protobuf」と略されることも)と HTTP/2 を利用したRPCフレームワークです。
簡単に言えば、RPCのアップグレード版のようなものです。
通常のRPCフレームワークのように、ローカルでサブルーチンを呼び出すのと似た形で、リモートのサブルーチンを呼び出すことができます。
仕組み自体は「Remote Invocation」とか「Remote Method Invocation(RMI)」などと言われることもありますね。医療機器みたいな略称です。

また、このgRPCを使うことで以下のようなメリットが考えられます。

  • XMLやJSONを使用するよりも、軽量で高速なので高効率。
  • データ構造をプロトコルファイルとして定義し、使用言語と通信するファイルを自動的に生成してくれる。
  • 様々な言語がサポートされている。(詳細はgRPCの公式ドキュメントを参照ください。)

この記事では、gRPCとWebAPI(RESTを使用)をUnityで動かし、HTTP/2とHTTPの通信速度の調査と測定結果を比較していきます。
gRPCが実際どんなものなのか、見ていきましょう。

サンプル作成の準備

計測には、社内トレーニングも兼ねて自前で用意したサンプルを使います。
今回は、ユーザー同士でチャットができるネイティブアプリとサーバーを作りました。

使ったライブラリ・フレームワーク:

  • Protocol Buffers
  • grpc_unity_package
  • grpc (for C#)
  • Node.js
  • Express.js

参考リンク:

ミッション I. サンプルのチャットアプリを作る

今回は速度の計測が目的なので、gRPCの導入方法などについては割愛します。
サンプルアプリとサーバーの相関は画像のような構造です。
idea.png

マッチングサーバー

matching_server.png
サーバー画面では、サーバーのマッチングが表示されます。シンプル。
ここではgRPCによって接続が開かれます。

クライアントアプリ

client.png
クライアントアプリでは、マッチングサーバーに接続してリクエストが作成されます。
簡単に機能を紹介しておきます。

  1. ユーザーが参加するルームを作るとき、ホストが作成される。
  2. ユーザーは作成されたルームを選択してチャットに参加できる。

ミッション II. gRPCとRESTの比較

1. サーバーの通信テスト:JSON data (REST)と Binary data (gRPC)の比較

以下のようにprotoファイルを作成します。

nodejs/gRPC/protos/simple.proto
syntax = "proto3";

option csharp_namespace = "Simple.Grpc";

package simple;

// Request 
message SimpleRequest{
    string username = 1;
    string message = 2;
}

// Response 
message SimpleResponse{
    string username = 1;
    string message = 2;
}

// RPC method
service SimpleService{
    rpc SimpleSend (SimpleRequest) returns (SimpleResponse) {}
}

gRPCで通信するサーバーコードの作成(NodeJS)

nodejs/gRPC/server.js
let grpc = require("grpc");
var protoLoader = require("@grpc/proto-loader");

const server = new grpc.Server();
const SERVER_ADDRESS = "10.11.21.231:5001";

// Load protobuf
let proto = grpc.loadPackageDefinition(
    protoLoader.loadSync("protos/simple.proto", {
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true
    })
);


function SimpleSend(call, callback) {
    console.log(call.request);
    callback(null, { username: call.request.username, message: call.request.message });
}

// Define server with the methods and start it
server.addService(proto.simple.SimpleService.service, { SimpleSend: SimpleSend });

server.bind(SERVER_ADDRESS, grpc.ServerCredentials.createInsecure());

server.start();
#endFile


# install node module `npm install`
# install grpc loader `npm install --save grpc @grpc/proto-loader`
node ./nodejs/gRPC/server.js

ExpressJSで通信するサーバーコードの作成

nodejs/Express/server.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ extended: true, limit: '10mb' }));
app.use(bodyParser.json());
app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,Content-Type, Accept");
    next();
});
app.listen(5002, '10.11.21.231', function () {

    /***
     * Router
     ***/
    app.post('/', (req, res) => {
        console.log({ response: req.body });
        return res.send({ response: req.body })
    });

});
#endFile

# install node module `npm install`
node ./nodejs/Express/server.js

2. 実測

measurement_scene.png
まずはなんの変哲もない条件での通信をテストしてみます。

3. マルチキャストしてみる

multiplecast.png
さらに、複数ユーザーがこのアプリを使った時の通信速度も計測しました。

測定結果

CPU/GPU負荷

image1.png

gRPCとRESTの実測値

image8_fix.png

image5.png

gRPCでのマルチキャスト結果

image6.png

実測値をみると、結構違いがあるように思えますね。
やはりgRPCは軽くて速い、ということが言えそうです。

まとめ

数値でも体感でも結果自体は良好。

序盤でも挙げましたが、良い点に関しては実際に言われている通りという印象を受けます。

  • gRPCとREST(Express)の処理速度には大きな違いがあると言える。
  • 他のプロトコルと比べて、3〜10分の1くらいコンパクトに開発ができる。
  • 様々なプログラミング言語をサポートしていて、クラスを簡単に生成できる。

3つ目については、GOなどのライブラリもあるようですね。
また、今回はUnityで実験しましたが、ネイティブアプリだけではなく、Web用のライブラリもあるようなので、こちらでも実測してみたいです。
grpc/rpc-web

3
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?