gRPCはRPCのフレームワークの一つです。SOAPと同じ分類になりますが、SOAPとの違いは以下になります。
- IDLの記述が容易(かつ人間が読める)
- コードジェネレータにより様々な言語に対応
- プロトコルはHTTP/2
- デフォルトではメッセージフォーマットとしてProtocolBuffersを利用するため、シリアライズ、デシリアライズが高速
Rubyで試す
以下のコマンドでgemをインストール$ gem install grpc
$ gem install grpc-tools
protoファイルというインターフェース定義ファイルを作成
syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
コンパイル
$ mkdir lib
$ grpc_tools_ruby_protoc -I .--ruby_out=lib --grpc_out=lib ./helloworld.proto
サーバ側
#!/usr/bin/env ruby
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'helloworld_services_pb'
# GreeterServer is simple server that implements the Helloworld Greeter server.
class GreeterServer < Helloworld::Greeter::Service
# say_hello implements the SayHello rpc method.
def say_hello(hello_req, _unused_call)
Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")
end
def say_hello_again(hello_req, _unused_call)
Helloworld::HelloReply.new(message: "Hello again, #{hello_req.name}")
end
end
# main starts an RpcServer that receives requests to GreeterServer at the sample
# server port.
def main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:{PORT}', :this_port_is_insecure)
s.handle(GreeterServer)
s.run_till_terminated
end
main
クライアント側
#!/usr/bin/env ruby
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'helloworld_services_pb'
def main
stub = Helloworld::Greeter::Stub.new('{HOST_NAME}:{PORT}', :this_channel_is_insecure)
user = ARGV.size > 0 ? ARGV[0] : 'world'
message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
p "Greeting: #{message}"
message = stub.say_hello_again(Helloworld::HelloRequest.new(name: user)).message
p "Greeting: #{message}"
end
main
これだけでRPCが可能です。SOAPよりかなり簡単な印象。利用可能な言語もC++、Go、C#、Java、Java(Android向け)、Node、Ruby、Python、PHP、Objective-Cと一通り揃ってます。
Pythonで試す
ライブラリをインストール$ pip install grpcio
$ pip install grpcio-tools
Pythonの場合はコンパイルは以下のようなジェネレータスクリプトを書く必要があります
from grpc.tools import protoc
protoc.main(
(
'',
'-I.',
'--python_out=./lib',
'--grpc_python_out=./lib',
'./helloworld.proto',
)
)
あとはこのスクリプト(run_codegen.py)を起動させればコンパイルしてくれます
$ python ./run_codegen.py
サーバ側スクリプト
"""The Python implementation of the GRPC helloworld.Greeter server."""
from concurrent import futures
import time
import grpc
import sys
sys.path.append('lib')
import helloworld_pb2
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Greeter(helloworld_pb2.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def SayOK(self, request, context):
return helloworld_pb2.HelloReply(message='OK! %s!' % request.name)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
クライアント側スクリプト
"""The Python implementation of the GRPC helloworld.Greeter client."""
from __future__ import print_function
import grpc
import sys
sys.path.append('lib')
import helloworld_pb2
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
response = stub.SayOK(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
if __name__ == '__main__':
run()