For the complete documentation index, see llms.txt. This page is also available as Markdown.

Shutdown

Setelah kita bisa menyalakan server, pertanyaan selanjutnya adalah: bagaimana mematikannya dengan aman?

Dalam lingkungan produksi, server tidak boleh berhenti secara tiba-tiba. Ada permintaan yang sedang diproses, koneksi database yang terbuka, atau task latar belakang yang belum selesai. Mematikan server secara paksa (hard shutdown) dapat menyebabkan:

  • Response terputus di tengah jalan (client mendapat error)

  • Data tidak tersimpan dengan benar

  • State aplikasi menjadi korup

Go menyediakan mekanisme graceful shutdown untuk mengatasi masalah ini.

πŸ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

πŸ”— github.com/jacky-htg/workshop/tree/main/02-shutdown

2.1 Mendengarkan Sinyal dari OS

Langkah pertama adalah mengetahui kapan sistem operasi ingin mematikan aplikasi kita. Di Linux/Unix, proses menerima sinyal seperti:

  • SIGINT – dikirim saat user menekan Ctrl+C

  • SIGTERM – dikirim oleh kill, systemctl stop, atau docker stop

Kita bisa mendengarkan sinyal-sinyal ini menggunakan signal.Notify:

shutdown := make(chan os.Signal, 1)
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM)

Catatan: Channel harus buffered karena paket signal tidak akan memblokir saat mengirim sinyal.

2.2 Menggabungkan Dua Sumber Event dengan select

Sekarang aplikasi kita memiliki dua sumber event asinkron:

  1. Server error – terjadi jika server gagal berjalan (misal port sudah digunakan)

  2. Shutdown signal – terjadi jika OS meminta aplikasi berhenti

Kita menggunakan select untuk menangani keduanya secara bersamaan:

2.3 Implementasi Graceful Shutdown Lengkap

Berikut implementasi lengkap dengan strategi fallback: jika graceful shutdown gagal, kita paksa tutup dengan server.Close().

2.4 Keterbatasan Graceful Shutdown

Penting untuk memahami bahwa tidak semua skenario bisa ditangani dengan graceful shutdown:

Perbandingan Berbagai Skenario Shutdown:

Skenario

Graceful Shutdown

server.Close()

Data Loss Risk

Listrik mati

❌ Tidak jalan

❌ Tidak jalan

πŸ”΄ Tinggi

Kill -9 (SIGKILL)

❌ Tidak jalan

❌ Tidak jalan

πŸ”΄ Tinggi

Ctrl+C (SIGINT)

βœ… Jalan (jika di-handle)

Bisa dipanggil

🟒 Rendah

Kill / systemctl stop (SIGTERM)

βœ… Jalan (jika di-handle)

Bisa dipanggil

🟒 Rendah

Docker stop (SIGTERM)

βœ… Jalan (jika di-handle)

Bisa dipanggil

🟒 Rendah

Pesan penting: Tidak ada kode Go yang bisa berjalan saat listrik mati atau proses di-kill -9. Graceful shutdown hanya melindungi dari shutdown normal yang dikirim melalui sinyal OS.

2.5 Memahami Dua Metode Penutupan Server

Go menyediakan dua metode berbeda untuk menutup server. Pilih berdasarkan kebutuhan:

server.Close() – Penutupan Paksa

  • Menutup listener dan semua koneksi aktif seketika

  • Request yang sedang berjalan terputus, client mendapat connection reset

  • Non-blocking, langsung return

server.Shutdown(ctx) – Penutupan Bertahap

  • Menutup listener β†’ tidak menerima request baru

  • Menunggu semua request yang sedang berjalan selesai

  • Koneksi idle ditutup dengan normal

  • Blocking sampai selesai atau timeout

Aspek

server.Close()

server.Shutdown(ctx)

Menutup listener

βœ… Langsung

βœ… Setelah graceful

Koneksi aktif

❌ Diputus paksa (reset)

βœ… Ditunggu selesai

Request dalam proses

❌ Terputus, client dapat error

βœ… Diberi waktu selesai

Keep-Alive connections

❌ Ditutup paksa

βœ… Ditutup setelah idle

HTTP/2 streams

❌ Diputus

βœ… Ditunggu selesai

Menerima request baru

βœ… Langsung ditolak

βœ… Langsung ditolak

Idle connections

❌ Diputus paksa

βœ… Ditutup normal

Context support

❌ Tidak ada timeout

βœ… Bisa pakai timeout

Error return

βœ… Selalu return error (biasanya http.ErrServerClosed)

βœ… Return error jika timeout atau gagal

Blocking behavior

βœ… Non-blocking, langsung return

βœ… Blocking sampai semua koneksi selesai atau timeout

Use case

Force shutdown, testing, atau saat graceful gagal

Production graceful shutdown

Client experience

πŸ”΄ Connection reset / EOF

🟒 Mendapat response lengkap

Risk

⚠️ Data loss, corrupted state

βœ… Aman untuk data integrity

Praktik terbaik: Gunakan Shutdown sebagai cara utama, dan simpan Close sebagai fallback jika graceful gagal (seperti pada contoh kode di atas).

Ringkasan Bab 2

Di bab ini kita telah belajar:

  1. Mendengarkan sinyal OS (SIGINT, SIGTERM) menggunakan signal.Notify

  2. Menggabungkan multiple channel events dengan select

  3. Implementasi graceful shutdown dengan server.Shutdown

  4. Fallback mekanisme dengan server.Close

  5. Memahami keterbatasan graceful shutdown pada skenario ekstrem

Pada bab berikutnya, kita akan membahas bagaimana menangani data dalam format JSON β€” tulang punggung komunikasi API modern.

Last updated