Telegram Group & Telegram Channel
👣 Graceful Shutdown in Go

Любое приложение должно при завершении работы:

1. Закрыть точку входа (HTTP-сервер, очередь сообщений и т.д.), но сохранить исходящие соединения (БД, кэш) активными.
2. Дождаться окончания всех текущих запросов, и при превышении допустимого времени вернуть корректную ошибку.
3. Освободить критические ресурсы (соединения с БД, файловые блокировки, слушатели). :contentReference[oaicite:0]{index=0}

## 1. Обработка сигналов

В Unix-системах сигналы (`SIGTERM`, SIGINT, SIGHUP`) — это программные прерывания, уведомляющие процесс о необходимости завершения или перезагрузки конфигурации. По умолчанию Go-рантайм ловит многие сигналы, но для «мягкой» остановки обычно интересуют только `SIGTERM и SIGINT. :contentReference[oaicite:1]{index=1}


func main() {
// 1) Создаем канал для сигналов
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

// 2) Запускаем сервер и другую работу здесь...

// 3) Ждем сигнала
<-signalChan
fmt.Println("Received termination signal, shutting down…")
}


2. Таймаут для завершения
В Kubernetes по умолчанию даётся 30 секунд на грациозную остановку (terminationGracePeriodSeconds). Хорошей практикой является резервирование 20 % времени (примерно 6 секунд) на «подстраховку» завершения.


timeout := 25 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server forced to shutdown: %v", err)
}


3. Остановка приёма новых запросов
Метод http.Server.Shutdown закрывает
слушатели и не принимает новые соединения, при этом дожидаясь окончания активных хэндлеров. Однако в контейнеризированных окружениях нужно сначала «провалить» readiness-пробу, чтобы снять под из балансировщика, и только затем вызывать Shutdown.
VictoriaMetrics


var shuttingDown atomic.Bool

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
if shuttingDown.Load() {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
})

// При получении сигнала:
shuttingDown.Store(true)
// Ждем несколько секунд, пока traffic прекратится
time.Sleep(5 * time.Second)
server.Shutdown(ctx)


4. Обработка активных запросов
После вызова Shutdown(ctx) сервер ждет либо завершения всех соединений, либо истечения контекста. Чтобы уведомить свои хэндлеры о «скоро закрытии», используйте контекст:

a) Middleware с каналом отмены

func WithGracefulShutdown(next http.Handler, cancelCh <-chan struct{}) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := WithCancellation(r.Context(), cancelCh)
defer cancel()
next.ServeHTTP(w, r.WithContext(ctx))
})
}

b) BaseContext для всего сервера


ongoingCtx, cancelFn := context.WithCancel(context.Background())
server := &http.Server{
Addr: ":8080",
Handler: yourHandler,
BaseContext: func(_ net.Listener) context.Context { return ongoingCtx },
}
// После готовности к остановке:
cancelFn()
VictoriaMetrics


5. Освобождение ресурсов
Не закрывайте ресурсы сразу при получении сигнала — хэндлеры могут ими ещё пользоваться. Лучше дождаться окончания работы (или таймаута), а затем в обратном порядке инициализации вызвать Close. Стандартный приём в Go — defer:


db := connectDB()
defer db.Close()

cache := connectCache()
defer cache.Close()

ОС сама освободит память и файловые дескрипторы при завершении процесса, но для внешних систем (БД, брокеры сообщений) рекомендуются явные Close()/Flush() для корректного завершения транзакций и избежания потерь данных.
VictoriaMetrics

➡️ Таким образом, грациозная остановка Go-приложения сводится к трём шагам:

- Ловим нужные сигналы и переключаемся на собственную логику.
- Останавливаем приём новых запросов через Shutdown и/или провал readiness-пробы.
- Ждём завершения активных запросов в пределах таймаута и закрываем ресурсы в обратном порядке.

@golang_books
Please open Telegram to view this post
VIEW IN TELEGRAM



tg-me.com/golang_books/970
Create:
Last Update:

👣 Graceful Shutdown in Go

Любое приложение должно при завершении работы:

1. Закрыть точку входа (HTTP-сервер, очередь сообщений и т.д.), но сохранить исходящие соединения (БД, кэш) активными.
2. Дождаться окончания всех текущих запросов, и при превышении допустимого времени вернуть корректную ошибку.
3. Освободить критические ресурсы (соединения с БД, файловые блокировки, слушатели). :contentReference[oaicite:0]{index=0}

## 1. Обработка сигналов

В Unix-системах сигналы (`SIGTERM`, SIGINT, SIGHUP`) — это программные прерывания, уведомляющие процесс о необходимости завершения или перезагрузки конфигурации. По умолчанию Go-рантайм ловит многие сигналы, но для «мягкой» остановки обычно интересуют только `SIGTERM и SIGINT. :contentReference[oaicite:1]{index=1}


func main() {
// 1) Создаем канал для сигналов
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

// 2) Запускаем сервер и другую работу здесь...

// 3) Ждем сигнала
<-signalChan
fmt.Println("Received termination signal, shutting down…")
}


2. Таймаут для завершения
В Kubernetes по умолчанию даётся 30 секунд на грациозную остановку (terminationGracePeriodSeconds). Хорошей практикой является резервирование 20 % времени (примерно 6 секунд) на «подстраховку» завершения.


timeout := 25 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server forced to shutdown: %v", err)
}


3. Остановка приёма новых запросов
Метод http.Server.Shutdown закрывает
слушатели и не принимает новые соединения, при этом дожидаясь окончания активных хэндлеров. Однако в контейнеризированных окружениях нужно сначала «провалить» readiness-пробу, чтобы снять под из балансировщика, и только затем вызывать Shutdown.
VictoriaMetrics


var shuttingDown atomic.Bool

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
if shuttingDown.Load() {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
})

// При получении сигнала:
shuttingDown.Store(true)
// Ждем несколько секунд, пока traffic прекратится
time.Sleep(5 * time.Second)
server.Shutdown(ctx)


4. Обработка активных запросов
После вызова Shutdown(ctx) сервер ждет либо завершения всех соединений, либо истечения контекста. Чтобы уведомить свои хэндлеры о «скоро закрытии», используйте контекст:

a) Middleware с каналом отмены

func WithGracefulShutdown(next http.Handler, cancelCh <-chan struct{}) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := WithCancellation(r.Context(), cancelCh)
defer cancel()
next.ServeHTTP(w, r.WithContext(ctx))
})
}

b) BaseContext для всего сервера


ongoingCtx, cancelFn := context.WithCancel(context.Background())
server := &http.Server{
Addr: ":8080",
Handler: yourHandler,
BaseContext: func(_ net.Listener) context.Context { return ongoingCtx },
}
// После готовности к остановке:
cancelFn()
VictoriaMetrics


5. Освобождение ресурсов
Не закрывайте ресурсы сразу при получении сигнала — хэндлеры могут ими ещё пользоваться. Лучше дождаться окончания работы (или таймаута), а затем в обратном порядке инициализации вызвать Close. Стандартный приём в Go — defer:


db := connectDB()
defer db.Close()

cache := connectCache()
defer cache.Close()

ОС сама освободит память и файловые дескрипторы при завершении процесса, но для внешних систем (БД, брокеры сообщений) рекомендуются явные Close()/Flush() для корректного завершения транзакций и избежания потерь данных.
VictoriaMetrics

➡️ Таким образом, грациозная остановка Go-приложения сводится к трём шагам:

- Ловим нужные сигналы и переключаемся на собственную логику.
- Останавливаем приём новых запросов через Shutdown и/или провал readiness-пробы.
- Ждём завершения активных запросов в пределах таймаута и закрываем ресурсы в обратном порядке.

@golang_books

BY Golang Books


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/golang_books/970

View MORE
Open in Telegram


Golang Books Telegram | DID YOU KNOW?

Date: |

Can I mute a Telegram group?

In recent times, Telegram has gained a lot of popularity because of the controversy over WhatsApp’s new privacy policy. In January 2021, Telegram was the most downloaded app worldwide and crossed 500 million monthly active users. And with so many active users on the app, people might get messages in bulk from a group or a channel that can be a little irritating. So to get rid of the same, you can mute groups, chats, and channels on Telegram just like WhatsApp. You can mute notifications for one hour, eight hours, or two days, or you can disable notifications forever.

How to Invest in Bitcoin?

Like a stock, you can buy and hold Bitcoin as an investment. You can even now do so in special retirement accounts called Bitcoin IRAs. No matter where you choose to hold your Bitcoin, people’s philosophies on how to invest it vary: Some buy and hold long term, some buy and aim to sell after a price rally, and others bet on its price decreasing. Bitcoin’s price over time has experienced big price swings, going as low as $5,165 and as high as $28,990 in 2020 alone. “I think in some places, people might be using Bitcoin to pay for things, but the truth is that it’s an asset that looks like it’s going to be increasing in value relatively quickly for some time,” Marquez says. “So why would you sell something that’s going to be worth so much more next year than it is today? The majority of people that hold it are long-term investors.”

Golang Books from cn


Telegram Golang Books
FROM USA