go之gRPC入門

gRPC 是一個高性能、開源和通用的 RPC 框架,基於HTTP2.0實現,具體原理及其他不再多說,百度/google有很多文章,這裏主要分享一下如何搭建grpc環境以及如何用插件自動生成*.pb.go代碼(以下分享均基於CentOs7)

下文中如果echo $GOPATH爲空,則請用絕對路徑代替GOPATH

一、gRPC開發環境搭建

1、安裝golang:

        yum install -y golang(安裝成功後輸入go version可以看到對應版本號)

2、創建工程目錄:

        mkdir -p $GOPATH/src/learn/vendor/github.com/golang

        mkdir -p $GOPATH/src/learn/vendor/golang.org/x

        mkdir -p $GOPATH/src/learn/vendor/google.golang.org

3、從git上拉取項目依賴庫:

        由於git上這些倉庫都被牆了,拉的很慢或者經常失敗,在gitee上將相關倉庫同步了一份,方便開發學習                                                                    

git與gitee倉庫對照表
git倉庫地址 gitee倉庫地址 存放文件夾地址
https://github.com/grpc/grpc-go.git  https://gitee.com/it-monkey/grpc-go.git vendor/google.golang.org/grpc(需要將grpc-go重命名爲grpc)
https://github.com/google/go-genproto.git  https://gitee.com/it-monkey/go-genproto.git  vendor/google.golang.org/genproto(需要將go-genproto重命名爲genproto)
https://github.com/golang/protobuf https://gitee.com/it-monkey/protobuf.git vendor/github.com/golang/protobuf
https://github.com/protocolbuffers/protobuf-go.git https://gitee.com/it-monkey/protobuf-go.git vendor/google.golang.org/protobuf(需要將protobuf-go重命名爲protobuf)
https://github.com/golang/net.git https://gitee.com/it-monkey/net.git github.com/golang/net
https://github.com/golang/sys.git https://gitee.com/it-monkey/sys.git  github.com/golang/sys
https://github.com/golang/text.git https://gitee.com/it-monkey/text.git github.com/golang/text

        下面是我的目錄樹結構

        |-- github.com
        |   `-- golang
        |       `-- protobuf            //grpc的依賴庫
        |-- golang.org
        |   `-- x                            //grpc的依賴庫
        |       |-- net
        |       |-- sys
        |       `-- text
        `-- google.golang.org
            |-- genproto              //








protoc-gen-go-grpc的源碼
            |-- grpc                     //grpc源碼
            `-- protobuf              //
protoc-gen-go的源碼

4、gRPC Demo

其實剛纔拉的倉庫裏已經有了廣泛的demo,就在vendor/google.golang.org/grpc/examples/helloworld,將vendor/google.golang.org/grpc/examples/helloworld拷貝出來測試

拷貝helloworld Demo : cp  -r  $GOPATH/src/learn/vendor/google.golang.org/grpc/examples/helloworld  $GOPATH/src/learn/

進入server端編譯&運行:     cd $GOPATH/src/learn/helloworld/greeter_server

                                              go build main.go

                                               ./main

再開一個窗口編譯運行client:   cd $GOPATH/src/learn/helloworld/greeter_client

                                                 go build main.go

                                                 ./main

 


protoc + protoc-gen-go + protoc-gen-go-grpc

        下面是介紹編譯proto文件&自動生成*.pb.go的工具protoc + protoc-gen-go-grpc  (老版本用的是protoc-gen-go,我試過,最新的grpc只用老版本生成的.pb.go少很多東西,無法使用,網上查了一下,說是現在官方在工具這一塊變動較大)

1、先下載protoc

https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protoc-3.14.0-linux-x86_64.zip

下載之後解壓,將其中的bin目錄下的protoc文件放到$GOPATH/bin目錄下

再給與可執行權限chmod a+x protoc

將$GOPATH/bin加入PATH: export PATH=$PATH:$GOPATH/bin

2、安裝protoc-gen-go

go install $GOPATH/src/learn/vendor/google.golang.org/protobuf/cmd/protoc-gen-go

3、安裝protoc-gen-go-grpc

        其實上面我們已經將protoc-gen-go-grpc的源碼下載下來了(vendor/google.golang.org/grpc/cmd/protoc-gen-go-grpc),現在只需要編譯安裝到$GOPATH/bin下即可

        運行如下命令即可安裝

        go install $GOPATH/src/learn/vendor/google.golang.org/grpc/cmd/protoc-gen-go-grpc

要確保$GOPATH/bin下有如下3個文件

接下來簡單寫一個proto文件

syntax = "proto3";
package calc;

message CalcRequest{
    int32 a = 1;
    int32 b = 2;
}

message CalcReply{
    int32 ans = 1;
}

service Calc{
    rpc Add(CalcRequest) returns (CalcReply){}
}

很簡單,裏面只有一個Add方法,內容就不多介紹了,下面用protoc-gen-go-grpc生成一下試試

能生成calc_grpc.pb.go以及calc.pb.go即爲成功


下面再順帶把自己寫的測試的server以及client貼出來(參照官方的helloworld寫的)

先貼一下的的工程目錄

|-- calc
|   |--- calc_grpc.pb.go
|   |--- calc.pb.go
|   `--- calc.proto
|-- calcClient
|   `--- main.go
`-- calcServer
    `--- main.go






server端代碼

package main

import (
    "learn/gRpcTest/calc"
    "context"
    "google.golang.org/grpc"
    "log"
    "net"
)

const (
    port = ":10024"
)

type server struct{
    calc.UnimplementedCalcServer
}

func main(){
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    calc.RegisterCalcServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

func (s *server)Add(ctx context.Context, in *calc.CalcRequest)(*calc.CalcReply, error){
    log.Printf("server Add called, param1:%d, param2:%d", in.A, in.B)
    return &calc.CalcReply{
        Ans: in.A + in.B,
    }, nil
}

func (s *server)mustEmbedUnimplementedCalcServer() {}

client端代碼

package main

import (
    "learn/gRpcTest/calc"
    "context"
    "google.golang.org/grpc"
    "log"
    "time"
)

const(
    address     = "localhost:10024"
)

func main(){
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    client := calc.NewCalcClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    ans, err := client.Add(ctx, &calc.CalcRequest{
        A: 10,
        B: 20,
    })
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("10+20 = %d", ans.GetAns())
}

大家可以運行一下試試

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章