Matikan Aplikasi Spring Boot

1. Ikhtisar

Mengelola siklus hidup Aplikasi Spring Boot sangat penting untuk sistem yang siap produksi. Container Spring menangani pembuatan, inisialisasi, dan penghancuran semua Beans dengan bantuan ApplicationContext.

Penekanan dari artikel ini adalah fase penghancuran siklus hidup. Lebih khusus lagi, kita akan melihat berbagai cara untuk mematikan Aplikasi Spring Boot.

Untuk mempelajari lebih lanjut tentang cara menyiapkan proyek menggunakan Spring Boot, lihat artikel Spring Boot Starter, atau buka Konfigurasi Spring Boot.

2. Titik Akhir Shutdown

Secara default, semua titik akhir diaktifkan di Aplikasi Spring Boot kecuali / shutdown ; ini, tentu saja, bagian dari titik akhir Aktuator .

Berikut ketergantungan Maven untuk menyiapkannya:

 org.springframework.boot spring-boot-starter-actuator 

Dan, jika kami juga ingin menyiapkan dukungan keamanan, kami memerlukan:

 org.springframework.boot spring-boot-starter-security 

Terakhir, kami mengaktifkan titik akhir shutdown di file application.properties :

management.endpoints.web.exposure.include=* management.endpoint.shutdown.enabled=true endpoints.shutdown.enabled=true

Perhatikan bahwa kita juga harus mengekspos titik akhir aktuator yang ingin kita gunakan. Dalam contoh di atas, kami telah mengekspos semua titik akhir aktuator yang akan menyertakan titik akhir / shutdown .

Untuk mematikan aplikasi Spring Boot, kita cukup memanggil metode POST seperti ini :

curl -X POST localhost:port/actuator/shutdown

Dalam panggilan ini, port mewakili port aktuator.

3. Tutup Konteks Aplikasi

Kita juga bisa memanggil metode close () secara langsung menggunakan konteks aplikasi.

Mari kita mulai dengan contoh membuat konteks dan menutupnya:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run(); System.out.println("Spring Boot application started"); ctx.getBean(TerminateBean.class); ctx.close();

Ini menghancurkan semua biji, melepaskan kunci, lalu menutup pabrik kacang . Untuk memverifikasi penutupan aplikasi, kami menggunakan callback siklus hidup standar Spring dengan anotasi @PreDestroy :

public class TerminateBean { @PreDestroy public void onDestroy() throws Exception { System.out.println("Spring Container is destroyed!"); } }

Kami juga harus menambahkan kacang jenis ini:

@Configuration public class ShutdownConfig { @Bean public TerminateBean getTerminateBean() { return new TerminateBean(); } }

Berikut outputnya setelah menjalankan contoh ini:

Spring Boot application started Closing [email protected] DefaultLifecycleProcessor - Stopping beans in phase 0 Unregistering JMX-exposed beans on shutdown Spring Container is destroyed!

Hal penting yang perlu diingat di sini: saat menutup konteks aplikasi, konteks induk tidak terpengaruh karena siklus proses yang terpisah .

3.1. Tutup Konteks Aplikasi Saat Ini

Dalam contoh di atas, kami membuat konteks aplikasi anak, lalu menggunakan metode close () untuk menghancurkannya.

Jika kita ingin menutup konteks saat ini, salah satu solusinya adalah dengan memanggil aktuator / titik akhir shutdown .

Namun, kami juga dapat membuat titik akhir kustom kami sendiri:

@RestController public class ShutdownController implements ApplicationContextAware { private ApplicationContext context; @PostMapping("/shutdownContext") public void shutdownContext() { ((ConfigurableApplicationContext) context).close(); } @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.context = ctx; } }

Di sini, kami telah menambahkan pengontrol yang mengimplementasikan antarmuka ApplicationContextAware dan menimpa metode penyetel untuk mendapatkan konteks aplikasi saat ini. Kemudian, dalam metode pemetaan, kami hanya memanggil metode close () .

Kami kemudian dapat memanggil titik akhir baru kami untuk menutup konteks saat ini:

curl -X POST localhost:port/shutdownContext

Tentu saja, jika Anda menambahkan titik akhir seperti ini dalam aplikasi kehidupan nyata, Anda juga ingin mengamankannya.

4. Keluar dari SpringApplication

SpringApplication mendaftarkan hook shutdown dengan JVM untuk memastikan aplikasi keluar dengan benar.

Beans dapat mengimplementasikan antarmuka ExitCodeGenerator untuk mengembalikan kode kesalahan tertentu:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class) .web(WebApplicationType.NONE).run(); int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() { @Override public int getExitCode() { // return the error code return 0; } }); System.exit(exitCode);

Kode yang sama dengan aplikasi Java 8 lambda:

SpringApplication.exit(ctx, () -> 0);

Setelah memanggil System.exit (exitCode) , program berakhir dengan kode pengembalian 0 :

Process finished with exit code 0

5. Hentikan Proses Aplikasi

Terakhir, kita juga dapat mematikan Aplikasi Spring Boot dari luar aplikasi dengan menggunakan skrip bash. Langkah pertama kami untuk opsi ini adalah membuat konteks aplikasi menulis PID-nya ke dalam file:

SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class) .web(WebApplicationType.NONE); app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid")); app.run();

Selanjutnya, buat file shutdown.bat dengan konten berikut:

kill $(cat ./bin/shutdown.pid)

Eksekusi shutdown.bat mengekstrak ID Proses dari file shutdown.pid dan menggunakan perintah kill untuk menghentikan aplikasi Boot.

6. Kesimpulan

In this quick write-up, we've covered few simple methods that can be used to shut down a running Spring Boot Application.

While it's up to the developer to choose an appropriate a method; all of these methods should be used by design and on purpose.

For example, .exit() is preferred when we need to pass an error code to another environment, say JVM for further actions. UsingApplicationPID gives more flexibility, as we can also start or restart the application with the use of bash script.

Finally, /shutdownis here to make it possible to terminate the applications externally via HTTP. For all the other cases .close() will work perfectly.

Seperti biasa, kode lengkap untuk artikel ini tersedia di proyek GitHub.