5
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.

Go、Node.jsのプログラム間でRPC通信をする

Last updated at Posted at 2019-12-15

#概要
gRPCを使用して、Go、Node.jsのプログラム間でRPC通信をします。
クライアント側をGo、サーバ側をNode.jsが担当します。

環境
MacOS Catalina: 10.15.1
Go: 1.13.4
Node.js: 10.15.3

#クライアント(Go)の作成
クライアント側のディレクトリを作成します。

$ mkdir grpc-test-go

クライアント側のディレクトリ構成は最終的に以下のようになります。

$ cd grpc-test-go
$ tree
.
├── bridge
│   ├── bridge.pb.go
│   ├── bridge.proto
│   └── go.mod
├── client.go
└── go.mod

###.protoファイルの作成

protoファイルを作成して、仕様を定義します。
型にrepeatedをつけると配列になります。
公式ページを参照してください。

bridge.proto
syntax = "proto3";

package bridge;

service BridgeService {
    rpc PostData (Data) returns (Reply) {}
} 

message Data {
    string key = 1;
    repeated string data = 2;
}

message Reply {
    string response = 1;
}

###.protoファイルからコードを生成
定義した.protoファイルからクライアント、サーバー共通で使用するコードを生成します。
まず、コードを生成するために必要なprotobufパッケージをインストールします。

$ brew install protobuf
$ protoc bridge/bridge.proto --go_out=plugins=grpc:.

これで、bridge.pb.goが作成されました

###module周りを整理
ローカルでbridge.pb.goを参照したいので、色々します。

$ go mod init grpc-test-go
$ cd bridge 
$ go mod init bridge

grpc-test-goの方のgo.modファイルを編集

go.mod
module grpc-test-go

go 1.13

require (
	github.com/[username]/grpc-test2/bridge v0.0.0
	google.golang.org/grpc v1.25.1
)

replace github.com/[username]/grpc-test-go/bridge => ./bridge

###クライアント側コードの作成

client.go
package main

import (
    "context"
    "fmt"
	"google.golang.org/grpc"
	pb "github.com/melonattacker/grpc-test-go/bridge"
)

func RpcPost(key string, Data []string) (string, error) {
	conn, err := grpc.Dial("127.0.0.1:50051", grpc.WithInsecure())
	if err != nil {
        return "", err
	}
	defer conn.Close()
	client := pb.NewBridgeServiceClient(conn)
	message := &pb.Data{Key: key, Data: Data}
	res, err := client.PostData(context.TODO(), message)
	response := res.Response
	if err != nil {
		return "", err
	}
	return response, nil
}

func main() {
	data := []string{"apple", "orange", "lemon"}
	result, err := RpcPost("fruit", data);
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result)
}
$ go build

コンパイルが通るはずです。

#サーバ(Node.js)の作成
サーバ側のディレクトリを作成します。
クライアント側と依存しない形で作成しましょう。

$ mkdir grps-test-node
$ cd grps-test-node

###.protoファイルの作成
上で作成したbridge.protoをコピーしてきます。

bridge.proto
syntax = "proto3";

package bridge;

service BridgeService {
    rpc PostData (Data) returns (Reply) {}
} 

message Data {
    string key = 1;
    repeated string data = 2;
}

message Reply {
    string response = 1;
}

###必要なnpmパッケージのインストール

$ npm init -y
$ npm install grpc @grpc/proto-loader --save

###サーバ側コードの作成

server.js
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const PROTO_PATH = __dirname + '/bridge.proto'

const packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true
    }
)

const BridgeProto = grpc.loadPackageDefinition(packageDefinition)

const server = new grpc.Server()

const PostData = (call, callback) => {
    console.log(call.request);
    callback(null, { response: "Data was sent to server with key: " + call.request.key })
}

server.addService(BridgeProto.bridge.BridgeService.service, {
    PostData: PostData,
})

server.bind('127.0.0.1:50051', grpc.ServerCredentials.createInsecure())
console.log('Listening on 127.0.0.1:50051...')
server.start()

#実行

###サーバ(Node.js)

$ cd grpc-test-node
$ node main.js
Listening on 127.0.0.1:50051...

###クライアント(Go)

$ cd grpc-test-go
$ go run client.go

###サーバ(Node.js)

{ data: [ 'apple', 'orange', 'lemon' ], key: 'fruit' }

###クライアント(Go)

Data was sent to server with key: fruit

無事データが送られました!
以上です!

5
2
2

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
5
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?