0Pricing
Go Academy · Урок

Потоковая передача между сервером и клиентом

Двунаправленная потоковая передача и обратное давление

«Потоковая передача между сервером и клиентом» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Типы потоковой передачи gRPC

Помимо унарного режима, gRPC поддерживает ещё три режима потоковой передачи: поток от сервера (сервер отправляет множество сообщений), поток от клиента (клиент отправляет множество сообщений) и двунаправленный поток (поток передают обе стороны).

Поток от сервера в .proto

Используйте ключевое слово stream перед типом ответа:

service EventService {
    rpc ListEvents (ListEventsRequest) returns (stream Event);
}

Реализация потока от сервера

Сервер отправляет несколько сообщений, вызывая stream.Send(), и возвращает nil после завершения:

func (s *server) ListEvents(req *pb.ListEventsRequest, stream pb.EventService_ListEventsServer) error {
    for _, event := range s.events {
        if err := stream.Send(event); err != nil { return err }
    }
    return nil
}

Получение потока от сервера клиентом

Клиент вызывает Recv() в цикле до тех пор, пока не получит io.EOF:

stream, err := client.ListEvents(ctx, &pb.ListEventsRequest{})
for {
    event, err := stream.Recv()
    if err == io.EOF { break }
    if err != nil { log.Fatal(err) }
    fmt.Println(event)
}

Поток от клиента в .proto

Используйте stream перед типом запроса:

service UploadService {
    rpc Upload (stream Chunk) returns (UploadResponse);
}

Реализация потока от клиента

Клиент отправляет несколько сообщений, а затем закрывает поток с помощью CloseAndRecv:

stream, _ := client.Upload(ctx)
for _, chunk := range chunks {
    stream.Send(chunk)
}
resp, err := stream.CloseAndRecv()

Получение потока от клиента сервером

Вызывайте stream.Recv() в цикле до тех пор, пока не получите io.EOF, а затем верните итоговый ответ:

func (s *server) Upload(stream pb.UploadService_UploadServer) error {
    for {
        chunk, err := stream.Recv()
        if err == io.EOF {
            return stream.SendAndClose(&pb.UploadResponse{Received: total})
        }
        if err != nil { return err }
        total += len(chunk.Data)
    }
}

Двунаправленный поток

И клиент, и сервер могут независимо отправлять и получать данные. В .proto укажите stream с обеих сторон.

service ChatService {
    rpc Chat (stream Message) returns (stream Message);
}

Реализация двунаправленного потока на сервере

Сервер получает данные в горутине и независимо отправляет их:

func (s *server) Chat(stream pb.ChatService_ChatServer) error {
    for {
        msg, err := stream.Recv()
        if err == io.EOF { return nil }
        if err != nil { return err }
        stream.Send(&pb.Message{Text: "echo: " + msg.Text})
    }
}

Управление потоком

gRPC использует управление потоком HTTP/2, чтобы быстрые отправители не перегружали медленных получателей. Вызовы Recv() естественным образом создают обратное давление — отправка блокируется, когда получатель не читает данные.

Отмена контекста

Передавайте контекст с крайним сроком или отменой во все вызовы потоковой передачи. Поток отменяется после завершения контекста, из-за чего Recv/Send возвращают ошибку.

Быстрая проверка

Как сервер RPC с потоком от сервера сообщает о завершении отправки?

Итоги: потоковая передача gRPC

Основные моменты:

  • Поток от сервера: ключевое слово stream у ответа; сервер вызывает Send()
  • Поток от клиента: ключевое слово stream у запроса; клиент вызывает Send(), затем CloseAndRecv()
  • Двунаправленный поток: stream с обеих сторон; независимые горутины Send и Recv
  • Отмена контекста применяется ко всем вызовам потоковой передачи

Часто задаваемые вопросы

Урок «Потоковая передача между сервером и клиентом» бесплатный?

Да — полный текст урока «Потоковая передача между сервером и клиентом» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Потоковая передача между сервером и клиентом»?

Двунаправленная потоковая передача и обратное давление Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Потоковая передача между сервером и клиентом»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Protocol Buffers и .proto-файлы
  2. Реализация унарного сервиса gRPC
  3. Потоковая передача между сервером и клиентом
  4. Перехватчики и метаданные gRPC
← Назад к Go Academy