服务端流
业务场景:用户积分
- .proto代码
// 用户积分模块
message UserInfo{
int32 user_id=1;
int32 user_score=2;
}
message UserScoreRequest{
repeated UserInfo users = 1;
}
message UserScoreResponse{
repeated UserInfo users =1;
}
service UserService{
rpc GetUserScore(UserScoreRequest) returns(UserScoreResponse);
rpc GetUserScoreByServerStream(UserScoreRequest) returns(stream UserScoreResponse);
}
- 生成protoc --go_out=…/services Product.proto protoc --go–grpc_out=…/services Product.proto
- 普通模式与s流模式对比 service.go代码:
// 服务端流模式 CS传输
func (s *UserService) GetUserScoreByServerStream(request *UserScoreRequest, stream UserService_GetUserScoreByServerStreamServer) error {
var score int32 = 101
users := make([]*UserInfo, 0)
for index, user := range request.Users {
user.UserScore = score
score++
users = append(users, user)
// 数据库协程
if (index+1)%2 == 0 && index > 0 { // 每隔两条发送
err := stream.Send(&UserScoreResponse{Users: users})
if err != nil {
return err
}
users = (users)[0:0] // 空切片
}
time.Sleep(time.Second*1) // 这里每一秒发送一些数据
}
if len(users)>0{
err2 := stream.Send(&UserScoreResponse{Users: users})
if err2!=nil{
return err2
}
}
return nil
}
// 普通模式 CS传输
func (s *UserService) GetUserScore(ctx context.Context, request *UserScoreRequest) (*UserScoreResponse, error) {
var score int32 = 101
users := make([]*UserInfo, 0)
for _, user := range request.Users {
user.UserScore = score
score++
users = append(users, user)
time.Sleep(time.Second*1) // 这里每5秒才发送全部数据
}
return &UserScoreResponse{Users: users}, nil
}
- server.go
func main(){
cert, _ := tls.LoadX509KeyPair("cert/server.pem", "cert/server.key")
certPool := x509.NewCertPool()
ca, _ := ioutil.ReadFile("cert/ca.pem")
certPool.AppendCertsFromPEM(ca)
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert}, // 服务端证书
ClientAuth: tls.RequireAndVerifyClientCert, // 双向验证
ClientCAs: certPool,
})
rpcServer := grpc.NewServer(grpc.Creds(creds)) // 传入证书
//rpcServer := grpc.NewServer() // 传入证书
services.RegisterProdServiceServer(rpcServer,new(services.ProdService)) // 注册商品服务
services.RegisterOrderServiceServer(rpcServer,new(services.OrderService)) // 注册订单服务
services.RegisterUserServiceServer(rpcServer,new(services.UserService)) // 用户积分服务
lis, _ := net.Listen("tcp", ":8081")
rpcServer.Serve(lis)
}
- client.go
// 用户积分模块,普通模式
userClient := NewUserServiceClient(conn)
var i int32
req := UserScoreRequest{}
req.Users=make([]*UserInfo,0)
for i = 1; i < 6; i++ {
req.Users=append(req.Users,&UserInfo{
UserId: i,
})
}
resUserSocre, _ := userClient.GetUserScore(context.Background(), &req)
fmt.Println(resUserSocre.Users)
// 用户积分模块2,客户端流模式
userClient2 := NewUserServiceClient(conn)
var i2 int32
req2 := UserScoreRequest{}
req2.Users=make([]*UserInfo,0)
for i2 = 1; i2 < 6; i2++ {
req2.Users=append(req2.Users,&UserInfo{
UserId: i2,
})
}
stream, err := userClient2.GetUserScoreByServerStream(context.Background(), &req2)
if err != nil {
log.Fatal(err)
}
for{ // 循环读流
recv, err := stream.Recv()
if err==io.EOF { // 当发送完数据时
break
}
if err!=nil{
log.Fatal(err)
}
fmt.Println(recv.Users) // 当获取到一条数据时,立即开协程去处理.实现一边接受,一边处理
}