4
3

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を導入してみた

Posted at
Page 1 of 2

gRPCとは?

Googleが開発したプロトコル
Protocol Buffers を使ってデータをシリアライズし、高速な通信を実現できる。
HTTP2.0を基盤としたRPC(リモートプロシージャコール)を実装するための技術

gRPCのメリット

  • .protoというファイル形式でクライアント側、サーバー側でコードを自動生成できる
    スキーマベースの開発となるため、連携のコミュニケーションが便利
  • クライアント側では、RESTのようにエンドポイントを呼び出す代わりに、メソッドを呼び出すような形で実行ができる
  • マイクロサービスアーキテクチャに向いている。主にサーバー間通信
  • HTTPの詳細部分を意識する必要がない
  • 処理が高速
  • 双方向通信が簡単に実装できる

HTTP2.0とは?

こちらの記事が参考になるので貼っておきます
そろそろ知っておきたいHTTP/2の話
なにが良くなったかざっくりとまとめると

  • リクエストの情報がテキストベースからシリアライズされたバイナリー形式になったことで解析時間が短くなった
  • TCPコネクションを複数貼る必要がなく、一つ貼って並列に実行ができる

RPCとは?

別のサーバーにある関数やメソッドを、ローカルで関数を呼びだすのと同じように実行することができる

Node.jsを使って実際に実装してみた

事前準備

今回はTypescriptを使って書くので、以下のライブラリをインストール

$ npm install nodemon ts-node typescript

grpcを使うために必要なライブラリを

  • grpc-tools
    .protoファイルからコードを生成するためのコマンドを提供する
  • grpc_tools_node_protoc_ts
    生成されたコードの型定義ファイル(.d.ts)も一緒に生成してくれる
  • @grpc/grpc-js
  • google-protobuf
$ npm install grpc-tools grpc_tools_node_protoc_ts --save-dev
$ npm install @grpc/grpc-js google-protobuf

.protoファイルの生成

packageは、別の.protoファイルでmessageのなどを利用する際に必要になる

.proto
syntax = "proto3";
package company;

service Company {
  rpc search (SearchRequest) returns (SearchResponse) {}
}

message SearchRequest {
  string text = 1;
}

message SearchResponse {
  repeated CompanyModel companies = 1;
}

message CompanyModel {
  string companyName = 1;
  bool isVenture = 2;
  bool isLarge = 3;
}

コードの生成

$ grpc_tools_node_protoc --plugin=protoc-gen-ts=node_modules/.bin/protoc-gen-ts --js_out=import_style=commonjs,binary:gen --grpc_out=grpc_js:gen --ts_out=grpc_js:gen -I ./src ./src/proto/*.proto

gen/proto以下にこのようなファイルが生成される
スクリーンショット 2021-06-25 8.50.59.png

server側の実装

.ts
import { sendUnaryData, ServerUnaryCall } from "@grpc/grpc-js";
import { SearchRequest, SearchResponse } from "../../../gen/proto/Company_pb";
export async function companyGrpcSearch(
    call: ServerUnaryCall<SearchRequest, SearchResponse>,
    callback: sendUnaryData<SearchResponse>
) {
    const response = new SearchResponse();
    const text = call.request.getText();
    response.setCompaniesList([])
    if (true) {
        callback(null, response);
    } else {
        // エラーを返す
        callback({code: Status.NOT_FOUND, details: 'あてはまる企業が存在しません'})
    }
}

client側の実装

import { credentials } from "@grpc/grpc-js";
import { CompanyClient } from "../gen/proto/Company_grpc_pb";
import {SearchRequest} from '../gen/proto/Company_pb';

const serverURL = `localhost:8080`;

export const grpcClientOptions = {
    "grpc.lb_policy_name": "round_robin",
    "grpc.dns_min_time_between_resolutions_ms": 5000,
    "grpc.keepalive_timeout_ms": 1000,
};

export type RequestParams = {
  text: string;
};
export async function search({ text = "" }: RequestParams) {
  const Request = new SearchRequest();
  const Client = new CompanyClient(
    serverURL,
    credentials.createInsecure(),
    grpcClientOptions
  );
  Request.setText(text);

  return new Promise((resolve, reject) => {
    Client.search(Request, (error, response) => {
      if (error) {
        console.error(error);
        reject({
          code: error?.code || 500,
          message: error?.message || "something went wrong",
        });
      }

      return resolve(response.toObject());
    });
  });
}

search({text: 'test'}).then((response) => console.log(response))
4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?