Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 611новых вакансий за сутки·93 573вакансии открыты сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 282
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 402 кандидата открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python16 842
  • Облачные технологии13 724
  • QA вакансии3 439
  • Backend вакансии2 083
  • Инженер данных1 763
  • Продакт-менеджер1 196

Разработка

  • Android1 842
  • iOS1 687
  • Fullstack вакансии958
  • AI вакансии949
  • Frontend вакансии735
  • Mobile вакансии44

По стеку

  • Go8 619
  • Java6 377
  • Node.js1 968
  • .NET1 639
  • Kotlin1 597
  • Rust1 444
  • PHP670
  • C#650
  • C++538

DevOps и инфраструктура

  • Kubernetes7 591
  • DevOps вакансии5 863
  • Linux-инфраструктура5 413
  • Terraform / IaC4 162
  • CI/CD2 997
  • Мониторинг и Observability1 752
  • SRE558
  • Кибербезопасность424

Аналитика и данные

  • Data Scientist1 087
  • Бизнес-аналитик910
  • Аналитик данных849
  • Системный аналитик148

Другие направления

  • Проджект-менеджер557
  • UI/UX дизайн139
  • Ручное тестирование14

По регионам

  • Вакансии в США45 355
  • Вакансии в Европе22 646
  • Вакансии в Канаде4 483
  • Работа в России3 902

По формату

  • Удалённые вакансии75 369
  • Релокация в США45 353
  • Гибридная работа12 002
  • Офисная работа7 033

По уровню

  • Senior вакансии42 326
  • Middle вакансии20 996
  • Junior вакансии6 757

Сейчас нанимают

Все компании
  • Wise192 вакансии
  • Rakuten189 вакансий
  • ASML163 вакансии
  • Grab139 вакансий
  • Celonis39 вакансий
  • Spotify36 вакансий
  • Adyen29 вакансий
  • Infobip28 вакансий
  • Monzo19 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме gRPC-GoВсе вопросы
gRPC-GoMiddleТеория

В чём разница между unary interceptors и stream interceptors в gRPC-Go?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Unary interceptors обрабатывают одиночные RPC-вызовы (аналог HTTP middleware). Stream interceptors оборачивают стриминговые RPC и получают объект ServerStream, позволяя перехватывать каждый Send/Recv через обёртку.

Unary Server Interceptor

Вызывается один раз для каждого Unary RPC. Сигнатура фиксирована: принимает контекст, запрос, информацию о методе и обработчик handler.

func LoggingUnaryInterceptor(
	ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler,
) (interface{}, error) {
	start := time.Now()
	resp, err := handler(ctx, req) // вызов реального метода
	log.Printf("%s duration=%s err=%v", info.FullMethod, time.Since(start), err)
	return resp, err
}

// Регистрация
s := grpc.NewServer(
	grpc.UnaryInterceptor(LoggingUnaryInterceptor),
)

Что такое interceptors в gRPC-Go

Interceptors — механизм middleware для gRPC, аналогичный HTTP-middleware. Они позволяют добавлять сквозную логику (логирование, аутентификацию, трейсинг, восстановление после паники) без изменения бизнес-кода. Существует два вида на стороне сервера и два на стороне клиента.

Stream Server Interceptor

Вызывается один раз при установке стриминга, но не для каждого отдельного сообщения. Чтобы перехватывать каждый Send/Recv, нужно обернуть grpc.ServerStream.

// Обёртка для перехвата сообщений потока
type wrappedStream struct {
	grpc.ServerStream
}

func (w *wrappedStream) RecvMsg(m interface{}) error {
	log.Printf("[stream] Recv: %T", m)
	return w.ServerStream.RecvMsg(m)
}

func (w *wrappedStream) SendMsg(m interface{}) error {
	log.Printf("[stream] Send: %T", m)
	return w.ServerStream.SendMsg(m)
}

func LoggingStreamInterceptor(
	srv interface{},
	ss grpc.ServerStream,
	info *grpc.StreamServerInfo,
	handler grpc.StreamHandler,
) error {
	start := time.Now()
	err := handler(srv, &wrappedStream{ss}) // передаём обёртку
	log.Printf("%s duration=%s err=%v", info.FullMethod, time.Since(start), err)
	return err
}

// Регистрация
s := grpc.NewServer(
	grpc.StreamInterceptor(LoggingStreamInterceptor),
)

Цепочка interceptors (chaining)

Начиная с grpc-go v1.34 доступны grpc.ChainUnaryInterceptor и grpc.ChainStreamInterceptor для регистрации нескольких interceptors:

s := grpc.NewServer(
	grpc.ChainUnaryInterceptor(
		RecoveryUnaryInterceptor,
		AuthUnaryInterceptor,
		LoggingUnaryInterceptor,
	),
	grpc.ChainStreamInterceptor(
		RecoveryStreamInterceptor,
		AuthStreamInterceptor,
	),
)

Клиентские interceptors

// Unary client interceptor — добавляет токен авторизации
func AuthUnaryClientInterceptor(token string) grpc.UnaryClientInterceptor {
	return func(
		ctx context.Context,
		method string,
		req, reply interface{},
		cc *grpc.ClientConn,
		invoker grpc.UnaryInvoker,
		opts ...grpc.CallOption,
	) error {
		ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+token)
		return invoker(ctx, method, req, reply, cc, opts...)
	}
}

conn, _ := grpc.NewClient(
	"localhost:50051",
	grpc.WithTransportCredentials(insecure.NewCredentials()),
	grpc.WithUnaryInterceptor(AuthUnaryClientInterceptor("my-token")),
)

Подводные камни

  • Нельзя зарегистрировать более одного interceptor через grpc.UnaryInterceptor() — вторая регистрация вызовет panic; используйте grpc.ChainUnaryInterceptor().
  • Stream interceptor вызывается только при открытии потока, а не для каждого сообщения; без обёртки ServerStream нельзя перехватить отдельные Send/Recv.
  • Panic-recovery interceptor должен быть первым в цепочке (самый внешний), иначе паника из другого interceptor не будет поймана.
  • При добавлении значений в контекст внутри interceptor используйте типизированные ключи (type ctxKey struct{}), а не строки — для избежания коллизий.
  • Interceptor, не вызвавший handler(), должен явно вернуть ошибку; молчаливый возврат nil создаст пустой ответ без обработки.
  • Трассировка через OpenTelemetry требует отдельных interceptors для Unary и Stream; пакет go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc предоставляет оба.
  • В stream interceptor info.IsClientStream и info.IsServerStream позволяют определить тип потока и применить разную логику для server/client/bidi streaming.

Частые вопросы на собеседовании

  • Как работает аутентификация в gRPC? Как реализовать TLS и mutual TLS (mTLS)?
  • Как реализовать token-based аутентификацию (JWT) в gRPC с помощью metadata?
  • Как реализовать gRPC-сервер на Go?
  • Каковы четыре типа паттернов взаимодействия gRPC? Объясните unary, server streaming, client streaming и bidirectional streaming.

Типичные ошибки

  • Давать ответ про unary и stream interceptors только на уровне определения, не показывая поведение в реальном приложении.
  • Игнорировать границы ответственности вокруг темы «unary и stream interceptors»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
  • Не связывать unary и stream interceptors с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.

Что проверяет интервьюер

  • Точно объясняет, что именно делает unary и stream interceptors и где это используется в Go-коде.
  • Связывает unary и stream interceptors с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
  • Не изобретает API и опирается на реальные контракты официальной документации.

Как вы знаете этот вопрос?

Проверить себя по теме gRPC-Go →

Источники

  • https://grpc.io/docs/guides/interceptors/
  • https://pkg.go.dev/google.golang.org/grpc
←Предыдущий вопросКогда следует выбирать gRPC вместо REST или GraphQL в микросервисной архитектуре?Следующий вопрос→В чём разница между `grpc.Dial()` и `grpc.NewClient()` в последних версиях gRPC-Go?

Связанные темы

gRPC-GoMiddlewareStreamingtechnical-reasoning