gRPC是一个高性能的RPC框架,面向移动和HTTP/2设计,目前提供了多种语言的支持,今天我们使用golang来体验一把。

go1.18

github地址:

protoc-3.20.0-win64.zip


D:\Environment\protoc-3.20.0\bin
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

创建golang的项目结构

helloworld
helloworld.proto
syntax = "proto3";

option go_package = "wy.com/grpcdemo/helloworld";
option java_multiple_files = true;
option java_package = "com.wy.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (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;
}

这个文件是gRPC框架中非常重要的一个文件,它定义了对外开放的服务,利用这个文件可以生成不同语言的客户端和服务端代码,达到相互调用的目的。

2)生成客户端和服务端代码

$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto
helloworld
go mode tidy
go.mod
module wy.com/grpcdemo/helloworld

go 1.18

require (
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.28.0
)

require (
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
)
greeterserver
main.go
package main

import (
   "context"
   "flag"
   "fmt"
   "google.golang.org/grpc"
   "log"
   "net"
   pb "wy.com/grpcdemo/helloworld"
)

var (
   port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
   pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
   log.Printf("Received: %v", in.GetName())
   return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
   flag.Parse()
   lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
   if err != nil {
       log.Fatalf("failed to listen: %v", err)
  }
   s := grpc.NewServer()
   pb.RegisterGreeterServer(s, &server{})
   log.Println("server listening at %v", lis.Addr())
   if err := s.Serve(lis); err != nil {
       log.Fatalf("failed to serve: %v", err)
  }
}
go.mod
module wy.com/grpcdemo/greeterserver

go 1.18

replace wy.com/grpcdemo/helloworld v1.1.0 => ../helloworld

require (
google.golang.org/grpc v1.45.0
wy.com/grpcdemo/helloworld v1.1.0
)

require (
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
wy.com/grpcdemo/helloworld
greeterclient
main.go
package main

import (
   "context"
   "flag"
   "google.golang.org/grpc"
   "google.golang.org/grpc/credentials/insecure"
   "log"
   "time"
   pb "wy.com/grpcdemo/helloworld"
)

const defaultName = "world"

var (
   addr = flag.String("addr", "localhost:50051", "the address to connect to")
   name = flag.String("name", defaultName, "Name to greet")
)

func main() {
   flag.Parse()
   conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
   if err != nil {
       log.Fatalf("did not connect: %v", err)
  }
   defer conn.Close()
   c := pb.NewGreeterClient(conn)

   //Contact the server and print out its response.
   ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   defer cancel()
   r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
   if err != nil {
       log.Fatalf("could not greet: %v", err)
  }
   log.Printf("Greeting: %s", r.GetMessage())
}
go.mod
module wy.com/grpcdemo/greeterclient

go 1.18

replace wy.com/grpcdemo/helloworld v1.1.0 => ../helloworld

require (
google.golang.org/grpc v1.45.0
wy.com/grpcdemo/helloworld v1.1.0
)

require (
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
wy.com/grpcdemo/helloworld

服务启动

1)启动服务端,在目录./grpcdemo/greeterserver下执行命令

$ go run main.go

2)启动客户端,在目录./grpcdemo/greeterclient下执行命令

$ go run main.go

go版本的gRPC框架Demo项目搭建已经完成,这里你可以启动其对应Java版本的服务端(Java版本的Demo看这里:),然后运行go版本的客户端,可以看到依然可以进行通信,所以这个框架还是可以在工作中尝试进行使用。

更多的功能有待进一步的挖掘。