gRPC
Contents
gRPC
环境准备
|
|
HelloWord
-
创建文件
./pb/hello_grpc.proto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
syntax = "proto3"; package hello_grpc; option go_package = "./;hello_grpc"; message Req { string message = 1; } message Res { string message = 1; } service HelloGRPC { rpc SayHi(Req) returns (Res); }
-
生成文件
1
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./pb/hello_grpc.proto
-
创建服务端文件
./server/main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
package main import ( "context" "fmt" "google.golang.org/grpc" "net" hello_grpc2 "test/grpc/01hello_word/pb" ) //1.取出server //2.挂载方法 //3.注册服务 //4.创建监听 // 1取出server type server struct { hello_grpc2.UnimplementedHelloGRPCServer } // SayHi 2挂载方法 func (s *server) SayHi(ctx context.Context, req *hello_grpc2.Req) (res *hello_grpc2.Res, err error) { fmt.Println(req.GetMessage()) return &hello_grpc2.Res{Message: "我是从服务端返回的信息"}, nil } func main() { // 3注册服务 listen, err := net.Listen("tcp", ":8888") if err != nil { fmt.Println("net.Listen err:", err) return } defer listen.Close() s := grpc.NewServer() hello_grpc2.RegisterHelloGRPCServer(s, &server{}) // 4创建监听 s.Serve(listen) }
-
创建客户端文件
./client/main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
package main import ( "context" "fmt" "google.golang.org/grpc" hello_grpc2 "test/grpc/01hello_word/pb" ) //1.创建链接 //2.new client //3.调用client //4.获取返回值 func main() { dial, err := grpc.Dial("127.0.0.1:8888", grpc.WithInsecure()) if err != nil { fmt.Println("grpc.Dial err:", err) } defer dial.Close() client := hello_grpc2.NewHelloGRPCClient(dial) hi, err := client.SayHi(context.Background(), &hello_grpc2.Req{Message: "我从客户端来"}) if err != nil { fmt.Println("client.SayHi err:", err) } fmt.Println(hi.GetMessage()) }
-
测试
proto文件详解
目录格式
基本格式
|
|
message
|
|
oneof 使用说明
-
proto
1 2 3 4 5 6 7 8 9 10 11 12 13
//省略前边 message Person { oneof TestOneOf{ string one = 6; string two = 7; string three = 8; } } service SearchService { rpc Search(Person) returns (Person); }
-
server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
func (s *spaceServer) Search(context context.Context, req *space.SpaceReq) (res *space.SpaceRes, err error) { name := req.GetName() fmt.Println(name) oneOf := req.TestOneOf switch v := oneOf.(type) { case *space.SpaceReq_One: fmt.Println(v.One) case *space.SpaceReq_Two: fmt.Println(v.Two) case *space.SpaceReq_Three: fmt.Println(v.Three) } res = &space.SpaceRes{ Name: "服务端", } return res, nil }
-
client
1 2 3 4 5 6 7 8 9 10 11 12 13
dial, err := grpc.Dial("127.0.0.1:8888", grpc.WithInsecure()) if err != nil { fmt.Println("grpc.Dial err:", err) } defer dial.Close() client := space.NewSearchServiceClient(dial) //及时相应 var p = space.SpaceReq{Name: "asdf", TestOneOf: &space.SpaceReq_One{One: "asdfasdf"}} hi, err := client.Search(context.Background(), &p) if err != nil { fmt.Println("client.SayHi err:", err) } fmt.Println(hi.GetName())
import引入其他proto
-
创建需要引入的proto
./pb/home/home.proto
1 2 3 4 5 6 7 8 9 10
syntax = "proto3"; //告诉编辑器 用 proto3 解读 package home; //包名 // go_package= "包路径(从mod下开始写);别名" option go_package = "test/grpc/02proto/pb/home;home"; message Home{ string name = 1; }
-
在需要引入文件中引入
1 2 3 4 5 6 7
//引入 import "home/home.proto"; message Person { //使用 home.Home i_home = 9; }
-
编译
1 2
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./person/person.proto protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./home/home.proto
service
使用 space包下文件
-
proto
./pb/space/space.proto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
syntax = "proto3"; package space; option go_package = "test/grpc/02proto/pb/space;space"; message SpaceReq{ string name = 1; } message SpaceRes{ string name = 1; } //定义服务 service SearchService { //即时响应 rpc Search(SpaceReq) returns (SpaceRes); //入参为流 rpc SearchIn(stream SpaceReq) returns (SpaceRes); //相应为流 rpc SearchOut(SpaceReq) returns (stream SpaceRes); //出入都为流 rpc SearchIO(stream SpaceReq) returns (stream SpaceRes); }
-
service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
package main import ( "context" "fmt" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" "net" "net/http" "test/grpc/02proto/pb/space" ) type spaceServer struct { space.UnimplementedSearchServiceServer } func (s *spaceServer) Search(context context.Context, req *space.SpaceReq) (res *space.SpaceRes, err error) { name := req.GetName() fmt.Println(name) res = &space.SpaceRes{ Name: "服务端", } return res, nil } func (s *spaceServer) SearchIn(server space.SearchService_SearchInServer) error { for { req, err := server.Recv() //传输结束 if err != nil { server.SendAndClose(&space.SpaceRes{Name: "完成了"}) break } fmt.Println(req) } return nil } func (s *spaceServer) SearchOut(req *space.SpaceReq, server space.SearchService_SearchOutServer) error { name := req.Name fmt.Println(name) for i := 0; i < 10; i++ { server.Send(&space.SpaceRes{Name: "服务端"}) } return nil } func (s *spaceServer) SearchIO(server space.SearchService_SearchIOServer) error { strChan := make(chan string, 1) go func() { for { recv, err := server.Recv() if err != nil { fmt.Println(err) strChan <- "结束" break } fmt.Println(recv) strChan <- recv.Name } }() for { name := <-strChan if "结束" == name { break } server.Send(&space.SpaceRes{Name: name}) } return nil } func main() { listen, err := net.Listen("tcp", ":8888") if err != nil { fmt.Println("net.Listen err", err) return } s := spaceServer{} server := grpc.NewServer() space.RegisterSearchServiceServer(server, &s) server.Serve(listen) }
-
client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
package main import ( "context" "fmt" "google.golang.org/grpc" "sync" "test/grpc/02proto/pb/space" ) func main() { dial, err := grpc.Dial("127.0.0.1:8888", grpc.WithInsecure()) if err != nil { fmt.Println("grpc.Dial err:", err) } defer dial.Close() client := space.NewSearchServiceClient(dial) //及时相应 //var p = space.SpaceReq{Name: "asdf", TestOneOf: &space.SpaceReq_One{One: "asdfasdf"}} //hi, err := client.Search(context.Background(), &p) //if err != nil { // fmt.Println("client.SayHi err:", err) //} //fmt.Println(hi.GetName()) //输入为流 //c, _ := client.SearchIn(context.Background()) //for i := 0; i < 10; i++ { // c.Send(&space.SpaceReq{Name: "哈哈哈"}) // time.Sleep(1 * time.Second) //} //recv, _ := c.CloseAndRecv() //fmt.Println(recv) //输出为流 //out, _ := client.SearchOut(context.Background(), &space.SpaceReq{Name: "1324"}) //for { // recv, err := out.Recv() // if err != nil { // fmt.Println(err) // break // } // fmt.Println(recv) //} //输入输出为流 group := sync.WaitGroup{} group.Add(1) io, _ := client.SearchIO(context.Background()) go func() { for { recv, err2 := io.Recv() if err2 != nil { fmt.Println(err2) group.Done() break } fmt.Println("服务端返回:", recv) } }() for i := 0; i < 10; i++ { err := io.Send(&space.SpaceReq{Name: "1324"}) if err != nil { fmt.Println(err) break } } io.CloseSend() group.Wait() }
grpc-gateway
安装插件
|
|
代码编写
-
proto
1 2 3 4 5 6 7 8 9
service SearchService { //即时响应 rpc Search(SpaceReq) returns (SpaceRes){ option(google.api.http) = { post:"/api/space", body:"*" }; }; }
-
编译
1
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative --grpc-gateway_out . --grpc-gateway_opt paths=source_relative ./space/space.proto
-
server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
func main() { go registerGetaway() listen, err := net.Listen("tcp", ":8888") if err != nil { fmt.Println("net.Listen err", err) return } s := spaceServer{} server := grpc.NewServer() space.RegisterSearchServiceServer(server, &s) server.Serve(listen) } //具体实现 func registerGetaway() { mux := runtime.NewServeMux() conn, _ := grpc.DialContext( context.Background(), "127.0.0.1:8888", grpc.WithBlock(), grpc.WithInsecure(), ) gwServer := &http.Server{ Handler: mux, Addr: ":8090", } space.RegisterSearchServiceHandler(context.Background(), mux, conn) gwServer.ListenAndServe() }
-
发送post请求测试