gRPC: そもそもRPC って何?
今回gRPC を学ぶ上でRPC
の説明をできるようにするためにRPCとはについてご説明します。
概要
リモートプロシージャコール(RPC)は、分散コンピューティングのサブルーチンです。
RPCのリモート実装はローカル呼び出しに似ていますが、通常は同じではありません。
RPCでは通常、オブジェクト名、関数名、またはパラメーターがリモートサーバーに渡され、 サーバーは処理された結果をクライアント側に返します(要求/応答)。
RPCは、TCP、UDP、またはHTTPプロトコルを介して通信できます。
Go での実装
今回はGoで server / client を実装して体験します。
Goでは、公式ドキュメントにあるように
明示的なCodecの指定をしない限り、gob
を使用してマーシャリングされます。
サーバーの実装
package main
import (
"fmt"
"log"
"net"
"net/rpc"
)
type Listener int
type Reply struct {
Data string
}
func (l *Listener) GetLine(line []byte, reply *Reply) error {
rv := string(line)
fmt.Printf("Receive: %v\n", rv)
*reply = Reply{rv}
return nil
}
func main() {
addy, err := net.ResolveTCPAddr("tcp", "0.0.0.0:12345")
if err != nil {
log.Fatal(err)
}
inbound, err := net.ListenTCP("tcp", addy)
if err != nil {
log.Fatal(err)
}
listener := new(Listener)
rpc.Register(listener)
rpc.Accept(inbound)
}
クライアントの実装
package main
import (
"bufio"
"log"
"net/rpc"
"os"
)
type Reply struct {
Data string
}
func main() {
client, err := rpc.Dial("tcp", "localhost:12345")
if err != nil {
log.Fatal(err)
}
in := bufio.NewReader(os.Stdin)
for {
line, _, err := in.ReadLine()
if err != nil {
log.Fatal(err)
}
var reply Reply
err = client.Call("Listener.GetLine", line, &reply)
if err != nil {
log.Fatal(err)
}
log.Printf("Reply: %v, Data: %v", reply, reply.Data)
}
}
in.ReadLine
の無限ループで受け取っているので、
client起動したら、文字を入力してEnter をしてください。
実行結果
clientからCallすると、サーバーで定義したGetLine
関数がcall されることがわかります。
REPO
今回の実装サンプルは以下に残しておきます。
https://github.com/locona/what-is-rpc-go