demo 路劲如下
grpc 开发三步走
- 编写.proto 文件定义服务
- 可以定义四种类型的服务方法:
- 普通 rpc: Unary RPCs
- 服务端流式 rpc: Server streaming RPCs
- 客户端流式 rpc: Client streaming RPCs
- 双向流式 rpc: Bidirectional streaming RPCs
syntax = "proto3";
package proto;
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
- 使用 protoc 编译 .proto 文件生成 .pb.go 文件
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./pd/*.proto
3. 实现服务端和客户端(编写业务逻辑)
- 服务端实现
// main.go
package main
import (
"fmt"
"net"
"context"
"hello_server/pd"
"google.golang.org/grpc"
)
// grpc server
type server struct {
pd.UnimplementedGreeterServer// 当你没有完全实现接口时,程序也是可以运行的
}
// 实现接口的标准格式
func (s *server) SayHello(ctx context.Context, in *pd.HelloRequest) (*pd.HelloResponse, error) {
return &pd.HelloResponse{Reply: "Hello " + in.Name}, nil
}
func main() {
// 启动服务
lis, err := net.Listen("tcp", ":8091")
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
s := grpc.NewServer()// 创建一个gRPC服务器
pd.RegisterGreeterServer(s, &server{})// 注册服务
// 启动服务
err = s.Serve(lis)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
- 客户端逻辑
- 也需要一份 .proto 文件
syntax = "proto3";// 版本声明
option go_package = "hello_client/proto"; // go_package go代码import路径
package pd;// 包声明,必须与server端一致
// 定义消息
message HelloRequest {
string name = 1;// 字段序号
}
// 定义响应消息
message HelloResponse {
string reply = 1;
}
// 定义服务
service Greeter {
// 定义rpc方法 入参: HelloRequest 出参: HelloResponse
rpc SayHello (HelloRequest) returns (HelloResponse);
}
注意:客户端和服务端都需要一份 .proto 文件
- 生成 go 代码
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./proto/*.proto
package main
import (
"log"
"time"
"context"
pd "hello_client/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
// 连接服务器
conn, err := grpc.NewClient("localhost:8091", grpc.WithTransportCredentials(insecure.NewCredentials()))// grpc.WithInsecure():不使用安全传输
if err != nil {
log.Fatalf("did not connect: %v", err)
return
}
defer conn.Close()// 关闭连接
// 创建客户端
c := pd.NewGreeterClient(conn)// GreeterClient是proto文件中定义的客户端
// 调用服务
// 执行RPC调用并打印收到的响应数据
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()// 取消上下文
r, err := c.SayHello(ctx, &pd.HelloRequest{Name: "hello world"})
if err != nil {
log.Fatalf("could not greet: %v", err)
return
}
log.Printf("Greeting: %s", r.GetReply())// r.GetReply()是proto文件中定义的响应数据
}
启动 hello_server服务 再启动 hello_client服务
- 如下:yes 成功了