О лекции

Gateway — единый вход: TLS, аутентификация, маршруты, лимиты. BFF — фасад под конкретный клиент. Оба полезны на краю. Оба становятся точкой отказа, если в них переезжает бизнес-логика.

Проектирование сервисов architecture собеседование

Клиенты не ходят в каждый под напрямую. Иначе CORS, N отдельных аутентификаций, смена внутренних URL и нет единого rate limit.

Gateway — дверь. Терминация TLS. Проверка JWT или сессии. Маршрутизация. Иногда грубая агрегация и кэш GET. Ingress в Kubernetes, Envoy, nginx, облачный LB — варианты одной роли.

Backend for Frontend — другой смысл. Подогнать DTO и оркестрацию под Web, iOS или партнёрский API.

Пример. Мобилка не хочет те же 15 полей, что админка. И не хочет сама собирать три сервиса. BFF режет overfetch и прячет внутренние модели. Это не замена доменным сервисам.

Что делает gateway

  • TLS, HTTP/2, иногда mTLS до mesh.
  • Authn на входе: JWT, сессия, API-ключ. Это не отменяет проверку полномочий внутри сервиса.
  • Rate limit и WAF — дёшево отсечь мусор до приложения.
  • Маршрутизация по пути и заголовкам, иногда канарейка по заголовку ревизии.
  • Таймауты и корреляционный id. Без них «200 на gateway и 30 с внутри» не собираются в картину.

BFF и толстый край

BFF оркестрирует два-три вызова под экран, мапит поля, режет payload. Бизнес-инвариант («нельзя списать дважды») остаётся в доменном сервисе.

Несколько BFF на разные клиенты нормальны. Один BFF «на все экраны мира» снова становится монолитом на краю.

package gateway

func Auth(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tok, err := bearer(r)
		if err != nil {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}
		claims, err := parseJWT(tok)
		if err != nil {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}
		r = r.WithContext(withUser(r.Context(), claims))
		next.ServeHTTP(w, r) // billing всё равно проверяет userID
	})
}

Край проверяет вход и маршрутизирует. Инвариант списания остаётся за сервисом.

Отказ и доверие

Падение gateway — падение продукта, если другого входа нет. Нужны реплики, health, лимиты CPU и FD, деградация: читать из кэша, отключить тяжёлую агрегацию.

Проверка JWT только на gateway без проверки сервисом нарушает zero-trust. Обошли mesh — сервис верит всем. Часто проверяют и на краю (дёшево), и внутри (полномочия на ресурс).

Пример. Таймаут на gateway 30 с, у сервиса 2 с. Клиент видит 504, а внутри хендлер ещё пишет в БД. Или наоборот: gateway обрывает, заказ создан, клиент думает, что нет, и жмёт ещё раз.

Типичная ошибка

Сложить бизнес-правила в nginx или Envoy, потому что так быстрее доставить фичу. Через год никто не знает, где инвариант. Вторая ловушка — разные таймауты на краю и внутри: клиент видит ошибку, работа в БД уже идёт.

На собеседовании

Нарисуйте клиент → gateway/BFF → сервисы. Край даёт TLS, лимит, маршруты. Сервис сам проверяет авторизацию на ресурс и идемпотентность. BFF — фасад под клиент, не второй монолит и не замена БД.