安装grpc
在你的项目目录下执行以下命令,获取 gRPC 作为项目依赖。
go get google.golang.org/grpc@latest
安装Protocol Buffers v3
安装用于生成gRPC服务代码的协议编译器,https://github.com/google/protobuf/releases
其中
- bin目录下的protoc是可执行文件
- include 目录下的是 google 定义的.proto文件,我们import "google/protobuf/timestamp.proto"就是从此处导入。
我们需要将下载得到的可执行文件protoc所在的 bin 目录加到我们电脑的环境变量中。
安装插件
我使用的是go语言开发,这里执行下面的命令安装protoc
的Go插件
安装go语言插件:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
该插件会根据.proto文件生成一个后缀为.pb.go的文件,包含所有.proto文件中定义的类型及其序列化方法。
安装grpc插件:
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
该插件会生成一个后缀为_grpc.pb.go的文件,其中包含:
- 一种接口类型(或存根) ,供客户端调用的服务方法。
- 服务器要实现的接口类型。
上述命令会默认将插件安装到 GOPATH/bin,为了protoc编译器能找到这些插件,请确保你的GOPATH/bin在环境变量中。
检查
依次执行以下命令检查一下是否开发环境都准备完毕。
3. 确认 protoc 安装完成。
❯ protoc --version
libprotoc 3.20.1
- 确认 protoc-gen-go 安装完成。
❯ protoc-gen-go --version
protoc-gen-go v1.28.0
如果这里提示protoc-gen-go不是可执行的程序,请确保你的 GOPATH 下的 bin 目录在你电脑的环境变量中。
- 确认 protoc-gen-go-grpc 安装完成。
❯ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.2.0
如果这里提示protoc-gen-go-grpc不是可执行的程序,请确保你的 GOPATH 下的 bin 目录在你电脑的环境变量中。
grpc的开发方式
- 编写
.proto
文件定义服务 - 生成指定语言的代码
syntax = "proto3"; // 版本声明,使用Protocol Buffers v3版本
option go_package = "xx"; // 指定生成的Go代码在你项目中的导入路径
package pb; // 包名
// 定义服务
service Greeter {
// SayHello 方法
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
// 请求消息
message HelloRequest {
string name = 1;
}
// 响应消息
message HelloResponse {
string reply = 1;
}
编写Server端代码
我们新建一个hello_server项目,在项目根目录下执行go mod init hello_server。
再新建一个pb文件夹,将上面的 proto 文件保存为hello.proto,将go_package按如下方式修改。
Windows执行:
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative pb/hello.proto
项目的目录结构
goodluck@goodluck MINGW64 /e/go_code/src/grpc/demo01/hello_server
$ tree
.
|-- go.mod
|-- go.sum
|-- hello_server.exe
|-- main.go
`-- pb
|-- hello.pb.go
|-- hello.proto
`-- hello_grpc.pb.go
在main.go中添加下面这段代码
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"grpc/demo01/hello_server/pb"
"net"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
reply := "hello" + in.GetName()
return &pb.HelloResponse{Reply: reply}, nil
}
func main() {
//启动服务
l, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Print("listen err:", err)
return
}
s := grpc.NewServer() //创建grpc服务
//注册服务
pb.RegisterGreeterServer(s, &server{})
// 启动
err = s.Serve(l)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
编译执行
编写Client端Go代码
我们新建一个hello_client
项目,在项目根目录下执行go mod init hello_client
。
再新建一个pb文件夹,将上面的 proto 文件保存为hello.proto,将go_package按如下方式修改。
...
option go_package = "hello_client/pb"; // 指定生成的Go代码在你项目中的导入路径
...
Windows执行
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative pb/hello.proto
此时项目目录结构为
goodluck@goodluck MINGW64 /e/go_code/src/grpc/demo01/hello_client
$ tree
.
|-- go.mod
|-- go.sum
|-- hello_client.exe
|-- main.go
`-- pb
|-- hello.pb.go
|-- hello.proto
`-- hello_grpc.pb.go
在http_client/main.go文件中按下面的代码调用http_server提供的 SayHello RPC服务。
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"grpc/demo01/hello_client/pb"
"time"
)
func main() {
// 连接到server端,此处禁用安全传输
coon, err := grpc.Dial(":8080", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
fmt.Printf("did not connect: %v", err)
return
}
defer coon.Close()
//创建客户端
c := pb.NewGreeterClient(coon)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
name := "小王"
resp, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
fmt.Printf("SayHello err: %v", err)
return
}
fmt.Println("resp:", resp.GetReply())
}
编译执行,得到结果:
resp: hello小王
说明执行成功