参考:
https://github.com/grpc/grpc-go
http://doc.oschina.net/grpc?t=60133
快速入门
建议grpc服务分三步:写proto文件、写serve、写client
proto文件
建立文件:proto/ServeRoute.proto
syntax = "proto3"; // 指定proto版本
package proto; // 指定包名
//定义传输过程用到的数据类型,数字代表内部成员序号
message Name {
string name = 1;
}
message Msg1 {
string message = 1;
}
message Msg2 {
Msg1 message = 1;
}
//定义提供的服务
service ServeRoute{
rpc Serve1(Name) returns (Msg1) {}
rpc Serve2(Name) returns (Msg2) {}
}
在proto文件所在的文件夹输入下面命令,生产pb.go文件
protoc --go_out=plugins=grpc:. ServeRoute.proto
serve文件
建立serve/serve.go
package main
import (
pb "../proto" // 引入编译生成的包
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
"net"
)
//通过一个结构体,实现proto中定义的所有服务
type ServeRoute struct{}
func (h ServeRoute) Serve1(ctx context.Context, in *pb.Name) (*pb.Msg1, error) {
log.Println("serve 1 works: get name: ", in.Name)
resp := &pb.Msg1{Message:"this is serve 1"}
return resp, nil
}
func (h ServeRoute) Serve2(ctx context.Context, in *pb.Name) (*pb.Msg2, error) {
log.Println("serve 2 works, get name: ", in.Name)
resp := &pb.Msg2{
Message:&pb.Msg1{Message:"this is serve 2"},
}
return resp, nil
}
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:50052") // Address gRPC服务地址
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
// 与http的注册路由类似,此处将所有服务注册到grpc服务器上,
pb.RegisterServeRouteServer(s, ServeRoute{})
log.Println("grpc serve running")
if err := s.Serve(listen); err != nil{
log.Fatal(err)
}
}
client文件
建立client/client.go(与serve分别为独立项目)
package main
import (
pb "../proto" // 引入proto包
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:50052", grpc.WithInsecure())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
c := pb.NewServeRouteClient(conn)
reqBody1 := &pb.Name{Name:"wang"}
res1, err := c.Serve1(context.Background(), reqBody1) //就像调用本地函数一样,通过serve1得到返回值
if err != nil {
log.Fatalln(err)
}
log.Println("message from serve: ", res1.Message)
reqBody2 := &pb.Name{Name:"li"}
res2, err := c.Serve2(context.Background(), reqBody2) //就像调用本地函数一样,通过serve2得到返回值
if err != nil {
log.Fatalln(err)
}
log.Println("message from serve: ", res2.Message.Message)
}
运行
运行serve.go之后
serve端等待请求:
2019/07/04 20:37:40 grpc serve running
运行client.go之后
serve端:
2019/07/04 20:37:51 serve 1 works: get name: wang
2019/07/04 20:37:51 serve 2 works, get name: li
client端:
2019/07/04 20:37:51 message from serve: this is serve 1
2019/07/04 20:37:51 message from serve: this is serve 2