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

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

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

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

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

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

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

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

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

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

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

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

Все подборки
  • Python8 752
  • Облачные технологии6 631
  • QA вакансии2 183
  • Android1 322
  • Инженер данных860
  • Продакт-менеджер316

Разработка

  • iOS1 238
  • Backend вакансии1 196
  • AI вакансии549
  • Fullstack вакансии500
  • Frontend вакансии426
  • Mobile вакансии28

По стеку

  • Go5 209
  • Java3 131
  • Kotlin1 113
  • Node.js1 008
  • Rust833
  • .NET656
  • PHP322
  • C++270
  • C#207

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

  • Kubernetes3 882
  • Linux-инфраструктура2 817
  • DevOps вакансии2 655
  • Terraform / IaC2 191
  • Мониторинг и Observability1 071
  • CI/CD919
  • SRE308
  • Кибербезопасность38

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

  • Аналитик данных522
  • Data Scientist435
  • Бизнес-аналитик397
  • Системный аналитик67

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

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

По регионам

  • Вакансии в США22 951
  • Вакансии в Европе10 259
  • Работа в России2 963
  • Вакансии в Канаде2 034

По формату

  • Удалённые вакансии39 691
  • Релокация в США22 951
  • Гибридная работа3 633
  • Офисная работа2 761

По уровню

  • Senior вакансии19 599
  • Middle вакансии11 130
  • Junior вакансии3 562

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

Все компании
  • Wise192 вакансии
  • Rakuten189 вакансий
  • ASML163 вакансии
  • Grab134 вакансии
  • Celonis42 вакансии
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

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

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

Как работают client/server interceptors и где реализовать auth, logging и retry?

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

Interceptors — это middleware для gRPC в Go. Unary и stream interceptors перехватывают вызовы на клиенте и сервере; через них реализуются auth, logging, retry и трейсинг, объединяемые цепочкой через grpc.ChainUnaryInterceptor.

Серверные interceptors

package main

import (
	"context"
	"log"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

// Auth interceptor — проверяет Bearer-токен в метаданных
func authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Error(codes.Unauthenticated, "missing metadata")
	}
	tokens := md.Get("authorization")
	if len(tokens) == 0 || !validateToken(tokens[0]) {
		return nil, status.Error(codes.Unauthenticated, "invalid token")
	}
	return handler(ctx, req)
}

// Logging interceptor — логирует метод, длительность и код ответа
func loggingInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	start := time.Now()
	resp, err := handler(ctx, req)
	st, _ := status.FromError(err)
	log.Printf("method=%s duration=%s code=%s", info.FullMethod, time.Since(start), st.Code())
	return resp, err
}

// Запуск сервера с цепочкой interceptors
func main() {
	s := grpc.NewServer(
		grpc.ChainUnaryInterceptor(
			loggingInterceptor, // выполняется первым
			authInterceptor,    // выполняется вторым
		),
	)
	// регистрация сервисов...
	_ = s
}

func validateToken(token string) bool {
	return token == "Bearer secret" // упрощённо
}

Что такое gRPC interceptors

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

Клиентские interceptors — retry

// Retry interceptor — повторяет запрос при временных ошибках
func retryInterceptor(maxAttempts int) grpc.UnaryClientInterceptor {
	return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		var err error
		for i := range maxAttempts {
			err = invoker(ctx, method, req, reply, cc, opts...)
			if err == nil {
				return nil
			}
			st, _ := status.FromError(err)
			if st.Code() != codes.Unavailable && st.Code() != codes.DeadlineExceeded {
				return err // не ретраить non-retryable ошибки
			}
			backoff := time.Duration(i+1) * 100 * time.Millisecond
			log.Printf("retry %d/%d after %s", i+1, maxAttempts, backoff)
			time.Sleep(backoff)
		}
		return err
	}
}

// Клиент с interceptors
func newClient() (*grpc.ClientConn, error) {
	return grpc.NewClient(
		"localhost:50051",
		grpc.WithChainUnaryInterceptor(
			retryInterceptor(3),
		),
	)
}

Stream interceptors

// Серверный stream interceptor для логирования
func streamLoggingInterceptor(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
	log.Printf("stream started: method=%s isClientStream=%v isServerStream=%v",
		info.FullMethod, info.IsClientStream, info.IsServerStream)
	err := handler(srv, ss)
	log.Printf("stream ended: method=%s err=%v", info.FullMethod, err)
	return err
}

// Регистрация stream interceptor
func newServerWithStream() *grpc.Server {
	return grpc.NewServer(
		grpc.ChainStreamInterceptor(streamLoggingInterceptor),
	)
}

Передача данных через контекст

Interceptors часто добавляют данные в контекст для следующих обработчиков. Используйте typed keys, чтобы избежать коллизий:

type contextKey string

const userIDKey contextKey = "userID"

func authInterceptorWithCtx(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	userID := extractUserID(ctx)
	ctx = context.WithValue(ctx, userIDKey, userID)
	return handler(ctx, req)
}

func extractUserID(ctx context.Context) string {
	return "user-123" // из JWT или metadata
}

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

  • Порядок в цепочке важен — logging должен быть внешним (первым), auth — внутренним. Иначе неаутентифицированные запросы не логируются или auth выполняется после бизнес-логики.
  • Паника в interceptor — если interceptor не перехватывает panic, сервер падает полностью. Нужен recovery interceptor как самый внешний в цепочке.
  • grpc.UnaryInterceptor vs grpc.ChainUnaryInterceptor — старый API grpc.UnaryInterceptor принимает только один interceptor. При передаче нескольких — только последний действует. Всегда используйте ChainUnaryInterceptor.
  • Context cancellation — retry-interceptor не проверяет ctx.Err() перед следующей попыткой, что ведёт к лишним запросам после таймаута клиента.
  • Stream interceptors сложнее unary — для добавления логики в каждое сообщение стрима нужно оборачивать grpc.ServerStream кастомной структурой, переопределяя RecvMsg/SendMsg.
  • Middleware от сторонних библиотек (go-grpc-middleware) — не все совместимы с актуальным grpc-go API (v1.64+), проверяйте совместимость версий.
  • Блокирующий retry без backoff — простой retry без экспоненциального отступа создаёт thundering herd при массовых отказах.

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

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

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

  • Отвечать определением без production-сценария.
  • Не называть runtime boundary, security boundary или failure mode.
  • Игнорировать версию API, observability и тестовую проверку.

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

  • Объясняет механизм своими словами и без выдуманных API.
  • Называет реальные риски, диагностику и критерий корректности.
  • Связывает ответ с текущей документацией и миграционными ограничениями.

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

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

Источники

  • https://grpc.io/about/
  • https://grpc.io/docs/what-is-grpc/core-concepts/

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

gRPC-Gogrpc-go-productionrisk-analysistechnical-depth