Jaka jest kolejność działań potrzebna do poprawnego zatrzymania aplikacji bez utraty danych lub awarii?
sobes.tech AI
Odpowiedź od AI
Aby poprawnie zatrzymać aplikację Go bez utraty danych i błędów, zwykle wykonuje się następujące kroki:
-
Obsługa sygnałów systemu operacyjnego — przechwytują sygnały zakończenia (
SIGINT,SIGTERM) za pomocą kanału isignal.Notify. -
Rozpoczęcie łagodnego zamknięcia (graceful shutdown) — uruchamiają procedurę płynnego zamknięcia, która przestaje przyjmować nowe żądania i pozwala na dokończenie istniejących.
-
Anulowanie kontekstu — używają
context.Contextz anulowaniem, aby przekazać sygnał zatrzymania wszystkim goroutine'om. -
Zamykanie zasobów — zamykają otwarte połączenia z bazami danych, plikami, połączeniami sieciowymi.
-
Oczekiwanie na zakończenie goroutine'ów — za pomocą
sync.WaitGrouplub innych mechanizmów czekają, aż wszystkie operacje się zakończą.
Przykład obsługi sygnału i łagodnego zamknięcia:
import (
"context"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
// Uruchomienie aplikacji
wg.Add(1)
go func() {
defer wg.Done()
runApp(ctx) // funkcja z główną logiką
}()
// Obsługa sygnałów
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs // czekanie na sygnał
cancel() // anulowanie kontekstu, sygnalizując goroutine'om
// Czekanie na zakończenie
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
// Wszystko zakończone
case <-time.After(10 * time.Second):
// Limit czasu oczekiwania
}
}
Ten sposób pomaga zapobiec utracie danych i nieprawidłowemu zamknięciu.