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 и опирается на реальные контракты официальной документации.