歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類和匯總,及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
本篇概覽
- 本文《gRPC學習》系列的第三篇,前文已準備好gRPC開發環境,今天一起來開發一個服務端應用以及遠程gRPC調用它的客戶端;
- 今天實戰的內容和步驟如下圖所示:
源碼下載
- 如果您不想編碼,可以在GitHub下載所有源碼,地址和鏈接信息如下表所示:
- 這個git項目中有多個文件夾,本章的應用在go-source文件夾下,如下圖紅框所示:
- go-source里面有多個子文件夾,本篇的源碼在helloworld中,如下圖紅框:
環境相關
- 接下來的開發都是在$GOPATH目錄下進行的,我這里的真實目錄是/home/golang/gopath;
- 在/home/golang/gopath/src目錄下新建helloworld目錄,作為接下來的實戰用到的目錄;
- 在完成本篇的所有開發后,最終$GOPATH/src/helloworld目錄下的內容如下:
[golang@centos7 src]$ tree helloworld/helloworld/├── client│ └── client.go├── helloworld.pb.go├── helloworld.proto└── server └── server.go2 directories, 4 files
編寫proto文件
- proto文件用來描述遠程服務相關的信息,如方法簽名、數據結構等,本篇的proto文件名為helloworld.proto,位置是$GOPATH/src/helloworld,內容如下:
// 協議類型syntax = "proto3";// 包名package helloworld;// 定義的服務名service Greeter { // 具體的遠程服務方法 rpc SayHello (HelloRequest) returns (HelloReply) {}}// SayHello方法的入參,只有一個字符串字段message HelloRequest { string name = 1;}// SayHello方法的返回值,只有一個字符串字段message HelloReply { string message = 1;}
根據proto生成go源碼
在helloworld.proto所在的目錄,執行以下命令:protoc --go_out=plugins=grpc:. helloworld.proto
如果helloworld.proto沒有語法錯誤,會在當前目錄生成文件helloworld.pb.go,這里面是工具protoc-gen-go自動生成的代碼,里面生成的代碼在開發服務端和客戶端時都會用到;下面是helloworld.pb.go的代碼片段,作用是服務注冊,入參是GreeterServer是個接口,由此可以推測:在服務端,由具體的業務代碼來實現GreeterServer接口,并且調用RegisterGreeterServer方法注冊,這樣客戶端遠程調用的服務就可以實現業務功能了:func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {s.RegisterService(&_Greeter_serviceDesc, srv)}type GreeterServer interface {// 具體的遠程服務方法SayHello(context.Context, *HelloRequest) (*HelloReply, error)}
借助GoLand的Structure面板,可以進一步觀察helloworld.pb.go:編寫服務端代碼server.go并啟動
在$GOPATH/src/helloworld目錄下新建文件夾server,在此文件夾下新建server.go,內容如下,已經添加詳細注釋:package mainimport ("context""log""net""google.golang.org/grpc"pb "helloworld")const (port = ":50051")// 定義結構體,在調用注冊api的時候作為入參,// 該結構體會帶上SayHello方法,里面是業務代碼// 這樣遠程調用時就執行了業務代碼了type server struct {// pb.go中自動生成的,是個空結構體pb.UnimplementedGreeterServer}// 業務代碼在此寫,客戶端遠程調用SayHello時,// 會執行這里的代碼func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {// 打印請求參數log.Printf("Received: %v", in.GetName())// 實例化結構體HelloReply,作為返回值return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil}func main() {// 要監聽的協議和端口lis, err := net.Listen("tcp", port)if err != nil {log.Fatalf("failed to listen: %v", err)}// 實例化gRPC server結構體s := grpc.NewServer()// 服務注冊pb.RegisterGreeterServer(s, &server{})log.Println("開始監聽,等待遠程調用...")if err := s.Serve(lis); err != nil {log.Fatalf("failed to serve: %v", err)}}
在server.go所在目錄執行go run server.go即可啟動服務,控制臺提示如下:[golang@centos7 server]$ go run server.go 2020/12/13 08:20:32 開始監聽,等待遠程調用...
此時gRPC的服務端已經啟動,可以響應遠程調用,接下來開發客戶端代碼;編寫客戶端代碼client.go并啟動
再打開一個控制臺;在$GOPATH/src/helloworld目錄下新建文件夾client,在此文件夾下新建client.go,內容如下,已經添加詳細注釋:package mainimport ("context""log""os""time""google.golang.org/grpc"pb "helloworld")const (address = "localhost:50051"defaultName = "world")func main() {// 遠程連接服務端conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())if err != nil {log.Fatalf("did not connect: %v", err)}// main方法執行完畢后關閉遠程連接defer conn.Close()// 實例化數據結構c := pb.NewGreeterClient(conn)// 遠程調用的請求參數,如果沒有從命令行傳入,就用默認值name := defaultNameif len(os.Args) > 1 {name = os.Args[1]}// 超時設置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())}
在client.go所在目錄執行go run client.go,會立即向服務端發起遠程調用,控制臺提示如下,可見得到了服務端的返回信息Hello world:[golang@centos7 client]$ go run client.go2020/12/13 08:38:05 Greeting: Hello world
再去服務端的控制臺看一下,通過日志發現業務代碼被執行,收到了遠程請求的參數:[golang@centos7 server]$ go run server.go 2020/12/13 08:20:32 開始監聽,等待遠程調用...2020/12/13 08:38:05 Received: world
回到客戶端控制臺,在命令行帶參數試試,輸入go run client.go abc,收到服務端響應如下:[golang@centos7 client]$ go run client.go abc2020/12/13 08:56:36 Greeting: Hello abc
再去服務端的控制臺看一下,成功收到了abc:[golang@centos7 server]$ go run server.go 2020/12/13 08:20:32 開始監聽,等待遠程調用...2020/12/13 08:38:05 Received: world2020/12/13 08:56:36 Received: abc
- 至此,一次常規的gRPC開發實戰就完成了,希望能給您一些參考,接下來的文章咱們會繼續深入學習gRPC;
歡迎關注我的公眾號:程序員欣宸
總結
以上是生活随笔為你收集整理的go获取项目内所有proto_gRPC学习之三:初试GO版gRPC开发的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。