У меня есть сервер 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, потому что создаю его внутри метода: (
Я думал о двух способах решения этой проблемы
- Имейте ссылку на клиента внутри
UserBackendServer
struct
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 клиентов ксвязаться с). Это нормально в производстве? Наличие всегда подключенных клиентов может привести к утечке памяти или слишком много параллельных соединений?
Использование методов, которые получают клиент в качестве аргумента
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
}
Писать все эти маленькие функции немного громоздко, и я не могу выполнить модульный тест серверной функции.
Стратегия номер один, осуществима ли? У вас есть опыт работы с ограничениями или как повторить неудачные соединения, если соединения поддерживаются в структуре сервера