Protocol Buffers
1.安装编译器
https://github.com/protocolbuffers/protobuf/releases
或者
sudo apt -y install protobuf-compiler
2.安装 go 插件
go get -u github.com/golang/protobuf/protoc-gen-go
3.编写 proto
https://developers.google.com/protocol-buffers/docs/proto3
https://developers.google.com/protocol-buffers/docs/gotutorial
字段标号:1~299-1 (536, 870, 911),其中 19000 ~ 19999 为保留的字段标号。
// 指定编译器版本,默认为 proto2 syntax = "proto3"; //package member; // 生成的 go 包名 option go_package = "./member"; message Member { // 字段类型 字段名 字段编号 string name = 1; uint32 age = 2; // 可重复字段,go 中为切片 repeated string emails = 3; } message Request { string msg = 1; } message Response{ uint32 code = 1; string msg = 2; repeated bytes data = 3; } service ProfileService { rpc CreateMember (stream Member) returns (Response) {} rpc GetMember (Request) returns (stream Member) {} }
应用
在 rpc 中的使用
代码生成
protoc ./member.proto --go_out=.
server.go
package main import ( "log" "net" "net/rpc" "member" ) type Profile struct{} func (pro *Profile) GetName(m *member.Member, resp *member.Response) error { resp.Msg = m.GetName() return nil } func main() { err := rpc.Register(&Profile{}) if err != nil { log.Fatalln(err) } ln, err := net.Listen("tcp", ":9008") if err != nil { log.Fatalln(err) } for { conn, err := ln.Accept() if err != nil { log.Println(err) continue } go rpc.ServeConn(conn) } }
client.go
package main import ( "log" "net/rpc" "member" ) func main() { m := &member.Member{ Name: "jack", Age: 27, Emails: []string{"jack@demo.com"}, } client, err := rpc.Dial("tcp", "127.0.0.1:9008") if err != nil { log.Fatalln(err) } defer client.Close() resp := &member.Response{} err = client.Call("Profile.GetName", m, resp) if err != nil { log.Fatalln(err) } log.Fatalln(resp.GetMsg()) }
在 grpc 中的使用
代码生成
protoc ./member.proto --go_out=plugins=grpc:.
证书生成
# Country Name (2 letter code) [AU]:CN # State or Province Name (full name) [Some-State]:SD # Locality Name (eg, city) []:QD # Organization Name (eg, company) [Internet Widgits Pty Ltd]:LANSEYUJIE # Organizational Unit Name (eg, section) []:DevOps # Common Name (e.g. server FQDN or YOUR name) []:grpc-demo # Email Address []:test@lanseyujie.com openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.cer -subj "/C=CN/ST=SD/L=QD/O=LANSEYUJIE/OU=DevOps/CN=grpc-demo/emailAddress=test@lanseyujie.com"
server.go
package main import ( "context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "io" "log" "net" "member" ) var memberList []*member.Member type Profile struct{} // Client Stream func (pro *Profile) CreateMember(stream member.ProfileService_CreateMemberServer) error { for { m, err := stream.Recv() if err != nil { if err == io.EOF { log.Println("EOF") resp := &member.Response{Code: 200, Msg: "all data recv"} return stream.SendAndClose(resp) } else { log.Println(err) return err } } memberList = append(memberList, m) // 输出接收到的数据 log.Println(m) } } // Server Stream func (pro *Profile) GetMember(req *member.Request, stream member.ProfileService_GetMemberServer) error { log.Println(req.GetMsg()) for _, m := range memberList { err := stream.Send(m) if err != nil { log.Println(err) return err } } return nil } // 拦截器 func TokenInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { md, exist := metadata.FromIncomingContext(ctx) if !exist { return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated") } var key, secret string if appKey, exist := md["appkey"]; exist { key = appKey[0] } if appSecret, exist := md["appsecret"]; exist { secret = appSecret[0] } if key != "abcd" || secret != "1234" { return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated") } // 继续下一步 return handler(ctx, req) } func main() { // TLS Server crd, err := credentials.NewServerTLSFromFile("./server.cer", "./server.key") if err != nil { log.Fatalln(err) } srv := grpc.NewServer(grpc.Creds(crd), grpc.UnaryInterceptor(TokenInterceptor)) // Pure Server // srv := grpc.NewServer() // 注册服务 member.RegisterProfileServiceServer(srv, &Profile{}) // 监听 tcp 端口 ln, err := net.Listen("tcp", ":9008") if err != nil { log.Fatalln(err) return } log.Fatalln(srv.Serve(ln)) }
client.go
package main import ( "context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "io" "log" "member" ) type Token struct { AppKey string AppSecret string } // metadata func (t *Token) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{ "appkey": t.AppKey, "appsecret": t.AppSecret, }, nil } // 是否使用 TLS 传输 func (t *Token) RequireTransportSecurity() bool { return true } // 调用 CreateMember 方法 func CreateMember(client member.ProfileServiceClient) { psc, err := client.CreateMember(context.Background()) if err != nil { log.Println(err) return } memberList := []*member.Member{ {Name: "jack", Age: 27, Emails: []string{"jack@demo.com"}}, {Name: "linda", Age: 33, Emails: []string{"linda@demo.com"}}, {Name: "tim", Age: 22, Emails: []string{"tim@demo.com"}}, } for _, m := range memberList { err = psc.Send(m) if err != nil { panic(err) } } for { resp, err := psc.CloseAndRecv() if err != nil { if err == io.EOF { log.Println("EOF") } else { log.Println(err) } break } log.Println(resp.GetMsg()) } } // 调用 GetMember 方法 func GetMember(client member.ProfileServiceClient) { req := &member.Request{Msg: "hello"} psc, err := client.GetMember(context.Background(), req) if err != nil { log.Println(err) return } for { m, err := psc.Recv() if err != nil { if err == io.EOF { log.Println("EOF") } else { log.Println(err) } break } log.Println(m) } } func main() { crd, err := credentials.NewClientTLSFromFile("./server.cer", "grpc-demo") if err != nil { log.Fatalln(err) } token := &Token{ AppKey: "abc", AppSecret: "1234", } // TLS conn, err := grpc.Dial("127.0.0.1:9008", grpc.WithTransportCredentials(crd), grpc.WithPerRPCCredentials(token)) // Pure // conn, err := grpc.Dial("127.0.0.1:9008", grpc.WithInsecure()) if err != nil { log.Fatalln(err) } defer conn.Close() client := member.NewProfileServiceClient(conn) CreateMember(client) GetMember(client) }
本文标题:grpc 在 golang 使用
版权声明:本文使用「署名-非商业性使用-相同方式共享」创作共享协议,转载或使用请遵守署名协议。