grpc
rpc是基于http2.0协议的
分为四个组件:
- 客户端(Client),服务的调用方。
- 服务端(Server),真正的服务提供者。
- 客户端存根(Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
- 服务端存根(Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。
4种请求和响应模式:
- 简单模式(Simple RPC):客户端发起请求并等待服务端响应。
rpc SayHello(HelloRequest) returns (HelloResponse){
}
- 服务端流式(Server-side streaming RPC):客户端发送请求到服务器,拿到一个流去读取返回的消息序列。 客户端读取返回的流,直到里面没有任何消息。
请求一次,客户端就可以源源不断的往服务端发送消息
// 注意stream位置
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
- 客户端流式(Client-side streaming RPC):与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。
请求一次,客户端就可以源源不断的往服务端发送消
// 注意stream位置
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
- 双向流式(Bidirectional streaming RPC):双方使用读写流去发送一个消息序列,两个流独立操作,双方可以同时发送和同时接收。类似tcp通信
// 注意stream位置
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}
server
// 实现SayHello接口
// 第一个参数是上下文参数,所有接口默认都要必填
// 第二个参数是我们定义的HelloRequest消息
// 返回值是我们定义的HelloReply消息,error返回值也是必须的。
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
// 创建一个HelloReply消息,设置Message字段,然后直接返回。
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
// 监听127.0.0.1:50051地址
lis, err := net.Listen("tcp", "127.0.0.1:50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 实例化grpc服务端
s := grpc.NewServer()
// 注册Greeter服务
pb.RegisterGreeterServer(s, &server{})
// 往grpc服务端注册反射服务
reflection.Register(s)
// 启动grpc服务
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
client
func main() {
// 连接grpc服务器
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
// 延迟关闭连接
defer conn.Close()
// 初始化Greeter服务客户端
c := pb.NewGreeterClient(conn)
// 初始化上下文,设置请求超时时间为1秒
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
// 延迟关闭请求会话
defer cancel()
// 调用SayHello接口,发送一条消息
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "world"})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
// 打印服务的返回的消息
log.Printf("Greeting: %s", r.Message)
}