Forwarded from Николай Тузов
Таймауты HTTP Server в Go - как работают и зачем нужны
В стандартной библиотеке Go есть замечательный пакет
- ReadHeaderTimeout - время, отводимое на чтение заголовков запроса
- ReadTimeout - максимальная продолжительность чтения полного запроса, включая тело
- WriteTimeout - максимальное время ожидания до окончания записи ответа
- IdleTimeout - максимальное время ожидания следующего запроса, используется keep-alive
Чтобы лучше уложить в голове, как они используются, давайте вспомним, как сервер работает с входящими запросами:
- Борьба с Slowloris атаками: это тип атаки, при которой злоумышленник устанавливает соединение с сервером и отправляет запрос нуу оооочень медленно. Это может приводить к исчерпанию ресурсов сервера и его последующему отказу. Установка
- Отправка больших данных: возможно, клиенты отправляют нам что-то очень большое, и мы не хотим чтобы это заняло слишком много времени. В этом случае помогает
- Ограничение использования ресурсов: При большом количестве запросов, особенно в микросервисных архитектурах, установка
————
☁️ Если я где-то ошибся или был неточен, пожалуйста, напишите об этом в комментах, я всё поправлю
💻 Идея написания этого поста возникла во время записи ролика по REST API, в котором у меня не хватило времени на полноценное объяснение
#гайды #golang #http
В стандартной библиотеке Go есть замечательный пакет
net/http
, в котором есть структура http.Server
. Это основная структура для написания сервиса, обрабатывающего HTTP запросы. У http.Server
довольно много интересных параметров, но здесь нам интересны таймауты:- ReadHeaderTimeout - время, отводимое на чтение заголовков запроса
- ReadTimeout - максимальная продолжительность чтения полного запроса, включая тело
- WriteTimeout - максимальное время ожидания до окончания записи ответа
- IdleTimeout - максимальное время ожидания следующего запроса, используется keep-alive
Чтобы лучше уложить в голове, как они используются, давайте вспомним, как сервер работает с входящими запросами:
1. Подключение установленоЗачем нужно столько таймаутов?
|--- ReadHeaderTimeout (если установлен) ---|
2. Заголовки запроса получены
|--- ReadTimeout (если установлен) ---|
3. Тело запроса получено, начинается обработка запроса
4. Обработка завершена, сервер начинает отправлять ответ
|--- WriteTimeout (если установлен) ---|
5. Ответ полностью отправлен клиенту
|--- IdleTimeout (если установлен и соединение остается открытым) ---|
6. Если не было другого запроса в течение IdleTimeout, соединение закрывается
7. Если новый запрос получен до IdleTimeout, процесс начинается сначала с шага 2
- Борьба с Slowloris атаками: это тип атаки, при которой злоумышленник устанавливает соединение с сервером и отправляет запрос нуу оооочень медленно. Это может приводить к исчерпанию ресурсов сервера и его последующему отказу. Установка
ReadHeaderTimeout
и ReadTimeout
может помочь.- Отправка больших данных: возможно, клиенты отправляют нам что-то очень большое, и мы не хотим чтобы это заняло слишком много времени. В этом случае помогает
ReadTimeout
- Обратная ситуация - работа с ооочень медленными клиентами: Встречаются клиенты со слабым каналом, которые принимают наш ответ очень долго (например, некоторые устройства IoT или просто регионы со слабым интернет-покрытием). В этом случае, если не установить WriteTimeout
, сервер может ждать бесконечно долго, пытаясь отправить ответ, что может привести к исчерпанию ресурсов.- Ограничение использования ресурсов: При большом количестве запросов, особенно в микросервисных архитектурах, установка
IdleTimeout
помогает освободить ресурсы от долгоживущих соединений, которые больше не используются.————
#гайды #golang #http
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥28👍16
Прокачали логгер, теперь взялись за HTTP-роутер
https://eli.thegreenplace.net/2023/better-http-server-routing-in-go-122/
- Proposal
- Документация
Пример кода:
1. В первом хэнделере мы видим явное указание HTTP-метода (GET)
2. Во втором - компонент
За ссылку спасибо @batazor
#go_updates #http #mux
https://eli.thegreenplace.net/2023/better-http-server-routing-in-go-122/
- Proposal
- Документация
Пример кода:
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /path/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "got path\n")
})
mux.HandleFunc("/task/{id}/", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprintf(w, "handling task with id=%v\n", id)
})
http.ListenAndServe("localhost:8090", mux)
}
1. В первом хэнделере мы видим явное указание HTTP-метода (GET)
2. Во втором - компонент
{id}
и r.PathValue("id")
для получения значенияЗа ссылку спасибо @batazor
#go_updates #http #mux
👍18❤2🔥2
routegroup - легковесная обёртка для группировки и интеграции middleware в
https://github.com/go-pkgz/routegroup
Автор библиотеки: Umputun, один из ведущих подкаста Радио-Т
Описание его словами:
Оригинальный пост: https://t.me/daily_geek_news/218
#library #http #mux
http.ServeMux
https://github.com/go-pkgz/routegroup
Автор библиотеки: Umputun, один из ведущих подкаста Радио-Т
Описание его словами:
Смысл этой микро-библиотеки лично для меня в том, чтоб убрать ненужную теперь зависимость на Chi в моих проектах, но не пострадать при этом. Chi мне служил верой и правдой много лет, хотя наши с ним (а точнее с его автором) отношения не всегда были ровными. Однако, после того как в 1.22 завезли улучшения раутинга, почти все, чего мне не хватало в стандартном муксе там появилось. Единственно то, чего не хватило это библиотека добавила, а именно группы раутов с ассоциированными мидлеваре.
Я ее писал с двумя целями в голове - добавить только это и ничего более, и быть полностью совместимым со стандартной библиотекой.
Оригинальный пост: https://t.me/daily_geek_news/218
#library #http #mux
GitHub
GitHub - go-pkgz/routegroup: Lightweight library for route grouping and middleware integration with the standard http.ServeMux
Lightweight library for route grouping and middleware integration with the standard http.ServeMux - go-pkgz/routegroup
🔥23👍5 2
Как я пишу HTTP сервисы на Go спустя 13 лет
How I write HTTP services in Go after 13 years
Мэт Райер (Grafana, Go Time podcast) делится опытом, как он пишет HTTP-сервисы после 13 лет работы с Go.
Ключевая мысль статьи: не нужен ни фреймворк, ни DI-магия, всё решается стандартной библиотекой и явными зависимостями.
TL;DR:
-
- Все роуты в одном месте (
-
- Тесты поднимают сервис целиком (с
- Хэндлеры собираются фабриками, middleware пишутся обычными функциями func(h http.Handler) http.Handler — всё просто и прозрачно.
————
🟢 Что я могу сказать.. Такое ощущение, будто статью писал я сам. Хочу, чтобы каждый мой коллега прочитал её дважды ! Я устал регулярно объяснять и защищать все те простые вещи, о которых пишет автор.
Мне даже 13 лет на это не понадобилось, просто учителя были хорошие👴
Единственное, что вызывает вопросы — это «nil-зависимости» в тестах (автор иногда передаёт nil, если зависимость не используется). Я бы всё же предпочёл простые no-op фейки, чтобы не ловить паники внезапно, пусть даже в тестах — поверьте, фиксить тесты без должной гигиены та ещё морока. Пусть сегодня в конкретном кейсе дело не доходит до какой-то зависимости, но завтра дойдёт.
В остальном подход отличный: код простой и читаемый, тесты пишутся легко, нет магии. Отличная статья, особенно для тех, кто только ещё не набил руку в архитектуре сервисов на Go❤️
Для новичков must read, опытным товарищам тоже лишним не будет ознакомиться.
#article #http #architecture #english
How I write HTTP services in Go after 13 years
Мэт Райер (Grafana, Go Time podcast) делится опытом, как он пишет HTTP-сервисы после 13 лет работы с Go.
Ключевая мысль статьи: не нужен ни фреймворк, ни DI-магия, всё решается стандартной библиотекой и явными зависимостями.
TL;DR:
-
NewServer(...)
принимает все зависимости конструктором и возвращает http.Handler
. Да, список аргументов может быть длинным, и это нормально — зато всё явно.- Все роуты в одном месте (
routes.go
), никакой путаницы.-
main()
тонкий, реальная логика в run(ctx, ...)
— удобно и для тестов, и для graceful shutdown.- Тесты поднимают сервис целиком (с
/readyz
и прочим), а окружение передаётся как параметры функции, без обращения к глобальному состоянию (os.Getenv
, flag
, os.Stdin/Stdout
)- Хэндлеры собираются фабриками, middleware пишутся обычными функциями func(h http.Handler) http.Handler — всё просто и прозрачно.
————
Мне даже 13 лет на это не понадобилось, просто учителя были хорошие
Единственное, что вызывает вопросы — это «nil-зависимости» в тестах (автор иногда передаёт nil, если зависимость не используется). Я бы всё же предпочёл простые no-op фейки, чтобы не ловить паники внезапно, пусть даже в тестах — поверьте, фиксить тесты без должной гигиены та ещё морока. Пусть сегодня в конкретном кейсе дело не доходит до какой-то зависимости, но завтра дойдёт.
В остальном подход отличный: код простой и читаемый, тесты пишутся легко, нет магии. Отличная статья, особенно для тех, кто только ещё не набил руку в архитектуре сервисов на Go
Для новичков must read, опытным товарищам тоже лишним не будет ознакомиться.
#article #http #architecture #english
Please open Telegram to view this post
VIEW IN TELEGRAM
Grafana Labs
How I write HTTP services in Go after 13 years | Grafana Labs
Mat Ryer, principal engineer at Grafana Labs and host of the Go Time podcast, shares what he's learned from more than a dozen years of writing HTTP services in Go.
1🔥34🤔7❤5