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倉庫地址 | 存放文件夾地址 |
---|---|---|
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())
}
大家可以運行一下試試