Александр Гольцман
Микросервисы gRPC в Golang
Микросервисы gRPC в Golang
gRPC — это современный фреймворк для удаленного вызова процедур (RPC), разработанный Google. Он основан на протоколе HTTP/2 и использует формат сериализации Protocol Buffers (protobuf), что делает его эффективным и быстрым. gRPC отлично подходит для построения микросервисной архитектуры, позволяя сервисам взаимодействовать друг с другом через строго типизированные API.
В этой статье я расскажу, как использовать gRPC в Golang, объясню его основные принципы, покажу, как создать сервер и клиента, и разберу важные аспекты, такие как сериализация данных и обработка ошибок.
Что такое gRPC и почему он важен?
gRPC решает задачу эффективного взаимодействия между сервисами. В отличие от REST API, который использует текстовый формат JSON и HTTP/1.1, gRPC работает поверх HTTP/2 и использует бинарный формат Protocol Buffers. Это дает несколько преимуществ:
- Высокая производительность — бинарная сериализация быстрее и компактнее JSON.
 - Поддержка потоковой передачи данных — gRPC позволяет реализовывать стриминговые вызовы.
 - Языковая независимость — клиенты и серверы могут быть написаны на разных языках.
 - Автоматическая генерация кода — API описываются в файлах 
.proto, а на их основе создаются серверные и клиентские обертки. 
Создание микросервисов с использованием gRPC - это продвинутая тема, требующая глубокого понимания не только gRPC, но и принципов построения микросервисной архитектуры, работы с сетью и concurrency. Если вы хотите детальнее погрузиться в создание микросервисов и научиться эффективно использовать все инструменты Go для построения масштабируемых систем, приходите на наш большой курс Продвинутый Golang. На курсе 179 уроков и 22 упражнения, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.
Теперь давайте посмотрим, как использовать gRPC в Go.
Установка gRPC в Go
Перед началом работы необходимо установить пакет gRPC и компилятор Protocol Buffers:
go install google.golang.org/protobuf/cmd/protoc@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latestЭти инструменты нужны для генерации Go-кода из .proto файлов. Теперь добавим зависимости в проект:
go get google.golang.org/grpc
go get google.golang.org/protobufОпределение gRPC-сервиса
В gRPC API описывается с помощью файла .proto. Давайте создадим сервис для управления пользователями:
syntax = "proto3";
package user;
service UserService {
  rpc GetUser (UserRequest) returns (UserResponse);
}
message UserRequest {
  string id = 1;
}
message UserResponse {
  string id = 1;
  string name = 2;
  string email = 3;
}Смотрите, здесь определен сервис UserService с одним методом GetUser, который принимает UserRequest (содержит id пользователя) и возвращает UserResponse (данные о пользователе).
Теперь сгенерируем код для Go:
protoc --go_out=. --go-grpc_out=. user.protoРеализация gRPC-сервера
Создадим сервер на Go, который будет реализовывать UserService:
package main
import (
    "context"
    "log"
    "net"
    "google.golang.org/grpc"
    pb "path/to/generated/userpb" // Импорт сгенерированного кода
)
// Реализация сервиса
type userServiceServer struct {
    pb.UnimplementedUserServiceServer
}
// Метод GetUser
func (s *userServiceServer) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
    log.Printf("Получен запрос на пользователя с ID: %s", req.Id)
    return &pb.UserResponse{
        Id:    req.Id,
        Name:  "Иван Иванов",
        Email: "ivan@example.com",
    }, nil
}
func main() {
    // Создаем TCP-сервер
    listener, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("Ошибка запуска сервера: %v", err)
    }
    grpcServer := grpc.NewServer()
    pb.RegisterUserServiceServer(grpcServer, &userServiceServer{})
    log.Println("gRPC сервер запущен на порту 50051")
    if err := grpcServer.Serve(listener); err != nil {
        log.Fatalf("Ошибка запуска сервера: %v", err)
    }
}Смотрите, что здесь происходит:
- Создаем сервер и реализуем 
UserServiceServer. - Определяем метод 
GetUser, который возвращает фиктивные данные о пользователе. - Запускаем сервер на порту 50051 и ожидаем подключения клиентов.
 
Реализация gRPC-клиента
Теперь создадим клиент, который будет отправлять запросы серверу:
package main
import (
    "context"
    "log"
    "time"
    "google.golang.org/grpc"
    pb "path/to/generated/userpb"
)
func main() {
    // Устанавливаем соединение с сервером
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Ошибка подключения: %v", err)
    }
    defer conn.Close()
    client := pb.NewUserServiceClient(conn)
    // Отправляем запрос
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    res, err := client.GetUser(ctx, &pb.UserRequest{Id: "123"})
    if err != nil {
        log.Fatalf("Ошибка при вызове GetUser: %v", err)
    }
    log.Printf("Получены данные о пользователе: ID=%s, Name=%s, Email=%s", res.Id, res.Name, res.Email)
}В этом коде:
- Создается клиент gRPC и устанавливается соединение с сервером.
 - Отправляется запрос 
GetUserсid = "123". - Выводятся полученные данные.
 
Теперь, если запустить сервер и затем клиента, клиент получит информацию о пользователе от сервера.
gRPC и REST: в чем разница?
gRPC часто сравнивают с REST API, так как оба способа позволяют сервисам взаимодействовать друг с другом.
| Функция | gRPC | REST | 
|---|---|---|
| Протокол | HTTP/2 | HTTP/1.1 | 
| Формат данных | Protocol Buffers | JSON | 
| Производительность | Высокая (бинарные данные) | Ниже (текстовые данные) | 
| Поддержка стриминга | Да | Нет | 
| Автогенерация кода | Да | Нет | 
Смотрите, если вам важна производительность, строгая типизация и поддержка потоков — gRPC будет лучшим выбором. Если же нужно простое взаимодействие между сервисами без сложной настройки, REST может быть более удобным.
Заключение
gRPC — это мощный инструмент для создания микросервисной архитектуры, который обеспечивает высокую скорость работы и удобную типизацию API. Он использует HTTP/2, бинарную сериализацию и автогенерацию кода, что делает его удобным для работы в распределенных системах.
gRPC - это мощный инструмент для создания микросервисов, но для его эффективного использования необходимо понимание многих нюансов, включая работу с protobuf, gRPC Gateway и service mesh. Чтобы получить все необходимые знания для построения современных микросервисных архитектур, рассмотрите возможность прохождения курса Продвинутый Golang. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир продвинутого Go прямо сегодня и станьте экспертом.
В этой статье я показал, как установить и использовать gRPC в Go, создать сервер, написать клиента и объяснил основные концепции. Попробуйте реализовать свой собственный gRPC-сервис и оцените его удобство на практике!
Постройте личный план изучения Golang до уровня Middle — бесплатно!
Golang — часть карты развития Backend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Golang
Лучшие курсы по теме

Основы Golang
Антон Ларичев
Nest.js с нуля
Антон Ларичев