1

我有一个与许多其他 GRPC 服务器通信的 GRPC 服务器。因此,我的服务器是许多其他 GRPC 服务器的客户端,我想测试我的服务器实现,但我一直坚持如何模拟 GRPC 客户端。

我有一个来自我的 GRPC 服务器的方法,如下所示:

func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    user, err := api.NewUserServiceClient(conn).
        UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

在这种类型的实现中,我不能模拟 UserServiceClient 因为我在方法中创建了一个:(

我想了两种方法来解决这个问题

  1. UserBackendServer在结构内有客户端引用
type UserBackendServer struct {
    projectID string
    userSvcClient api.UserServiceClient
}

func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    user, err := s.userSvcClient.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

有了这个实现,我就有了与客户端保持持续活动连接的副作用(我有 10 个客户端可以与之通信)。生产环境好吗?拥有始终连接的客户端会导致内存泄漏或过多的并发连接吗?

  1. 使用将客户端作为参数的方法
func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    client := api.NewUserServiceClient(conn)
    updateUser(ctx, req.UserId, req.User, client)


    user, err := s.userSvcClient.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

func updateUser(ctx context.Context, userId string, user *api.User, client api.UserServiceClient) (*api.User, error){
    userUpdated, err := client.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })

    return userUpdated, err
}

编写所有这些小功能似乎有点麻烦,我无法对服务器功能进行单元测试。

一号战略可行吗?如果连接保持在服务器结构中,您是否有关于限制或如何重试失败连接的经验

4

0 回答 0