Sobes.tech
Middle — Middle+

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:

  1. Obsługa sygnałów systemu operacyjnego — przechwytują sygnały zakończenia (SIGINT, SIGTERM) za pomocą kanału i signal.Notify.

  2. 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.

  3. Anulowanie kontekstu — używają context.Context z anulowaniem, aby przekazać sygnał zatrzymania wszystkim goroutine'om.

  4. Zamykanie zasobów — zamykają otwarte połączenia z bazami danych, plikami, połączeniami sieciowymi.

  5. Oczekiwanie na zakończenie goroutine'ów — za pomocą sync.WaitGroup lub 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.