FiberSeniorSystem design

Каковы компромиссы при использовании Fasthttp (движка Fiber) по сравнению со стандартным net/http Go?

Fasthttp даёт в 2–5 раз больше RPS за счёт zero-allocation буферов и пула goroutine, но несовместим со стандартным net/http: нет http.Handler, нет context.Context и части стандартных библиотек.

Fasthttp vs net/http: архитектурные различия

Стандартная библиотека net/http создаёт отдельную goroutine на каждое соединение, использует интерфейс http.Handler и интенсивно задействует сборщик мусора — каждый запрос аллоцирует http.Request, заголовки, body и прочие структуры.

Fasthttp (основа Fiber) работает по принципу worker-pool + zero-allocation: объекты RequestCtx берутся из пула sync.Pool и возвращаются обратно после обработки запроса. Это резко снижает давление на GC и увеличивает пропускную способность.

Измеримые преимущества Fasthttp

  • Throughput: на hello-world бенчмарках — 150 000–300 000 RPS против 50 000–80 000 у net/http (зависит от железа).
  • Латентность P99: меньше GC-пауз → стабильнее хвостовые задержки.
  • Память: в нагрузке fasthttp потребляет в 2–4 раза меньше heap, чем net/http.

Компромиссы и ограничения

  • Нет совместимости с net/http: middleware экосистема (Prometheus, OpenTelemetry, OAuth2-библиотеки) написана под http.Handler — с Fiber не работает напрямую.
  • Нет context.Context в RequestCtx: fasthttp.RequestCtx реализует context.Context только частично; передача стандартных deadline/cancel через весь стек — боль.
  • Строки — не []byte: Fiber/Fasthttp широко использует unsafe-преобразования []byte ↔ string для избежания аллокаций. Удержание ссылки на ctx.Body() после обработчика — UB (буфер возвращён в пул).
  • HTTP/2 и HTTP/3: Fasthttp не поддерживает HTTP/2 (нет PUSH, мультиплексирования). Для gRPC-over-HTTP/2 нужен net/http.
  • WebSocket: есть через github.com/fasthttp/websocket, но не через gorilla/websocket.

Когда выбрать net/http вместо Fiber

  • Нужна богатая экосистема middleware (chi, gorilla, go-kit).
  • Используете gRPC или HTTP/2 server push.
  • Код активно передаёт context.Context в БД/очереди — стандартная ctx-цепочка удобнее.
  • Команда незнакома с pitfall'ами zero-copy буферов.

Пример: эквивалентный хендлер на net/http и Fiber

// net/http
func stdHandler(w http.ResponseWriter, r *http.Request) {
	body, _ := io.ReadAll(r.Body)
	w.Header().Set("Content-Type", "application/json")
	w.Write(body) // body живёт столько, сколько нужно
}

// Fiber / Fasthttp
func fiberHandler(c *fiber.Ctx) error {
	body := c.Body() // указатель на пул-буфер!
	copy := make([]byte, len(body)) // ОБЯЗАТЕЛЬНО скопировать перед async-использованием
	copy = append(copy[:0], body...)
	return c.JSON(fiber.Map{"echo": string(copy)})
}

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

  • Удержание body после хендлера: c.Body() возвращает slice в пул после return — если сохранить в горутину, получите data race или мусор.
  • Middleware для net/http не подходит: попытка завернуть http.Handler без адаптера (adaptor.HTTPHandler) — паника в рантайме.
  • Отсутствие HTTP/2: CDN или балансировщик может negotiate HTTP/2, а бэкенд отвечает только HTTP/1.1 — важно документировать топологию.
  • Prefork + горутины: в prefork-режиме каждый процесс независим; глобальное состояние (кэш, счётчики) не синхронизируется между форками.
  • Streaming response: c.SendStreamWriter есть, но flush-семантика отличается от http.Flusher.
  • TLS-терминация: Fasthttp поддерживает TLS, но конфигурация tls.Config пробрасывается иначе, чем в net/http.
  • Трассировка OpenTelemetry: нужен отдельный пакет otelfiber — стандартный otelhttp не совместим.

Common mistakes

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

What the interviewer is testing

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

Sources

Related topics