All Products
Search
Document Center

Elastic Compute Service:Mendeteksi dan merespons event interupsi spot instans menggunakan Simple Message Queue

Last Updated:Apr 02, 2026

Spot instans dapat ditarik kembali kapan saja. Saat penarikan kembali akan segera terjadi, CloudMonitor mengirimkan notifikasi ke Simple Message Queue (SMQ), memberi aplikasi Anda waktu untuk menyimpan status dan membersihkan sumber daya. Panduan ini menjelaskan langkah-langkah lengkap pengaturannya: membuat antrian SMQ, berlangganan ke event interupsi ECS, mensimulasikan event, serta menulis penanganan yang mengambil dan memproses notifikasi tersebut.

Cara kerja

image

Ketika CloudMonitor mendeteksi event interupsi spot instans, notifikasi tersebut didorong ke antrian SMQ yang ditentukan dalam kebijakan langganan Anda. Aplikasi Anda melakukan polling terhadap antrian, mendekode isi pesan yang dikodekan Base64, lalu mengurai muatan JSON untuk mengidentifikasi instans yang terdampak. Setelah menangani event tersebut, hapus pesan dari antrian agar tidak diproses ulang.

Prasyarat

Sebelum memulai, pastikan Anda telah memiliki:

  • Akun Alibaba Cloud dengan Pengguna RAM yang dikonfigurasi untuk akses programatik. Akun Alibaba Cloud memiliki semua izin atas sumber daya. Jika pasangan AccessKey akun Alibaba Cloud Anda bocor, sumber daya Anda berisiko terpapar. Kami menyarankan Anda menggunakan pasangan AccessKey Pengguna RAM. Untuk informasi lebih lanjut, lihat Buat pasangan AccessKey.

  • Kebijakan AliyunMNSFullAccess yang dilampirkan pada Pengguna RAM

  • Kredensial AccessKey untuk Pengguna RAM yang disimpan sebagai variabel lingkungan (lihat Konfigurasikan variabel lingkungan di Linux, macOS, dan Windows)

  • Titik akhir SMQ yang telah dikonfigurasi (lihat Konfigurasikan titik akhir)

  • Java dan Maven yang telah diinstal

Tambahkan dependensi SDK SMQ

Tambahkan kode berikut ke file pom.xml Anda:

<dependencies>
    <!-- Alibaba Cloud SMQ SDK -->
    <dependency>
        <groupId>com.aliyun.mns</groupId>
        <artifactId>aliyun-sdk-mns</artifactId>
        <version>1.2.0</version>
    </dependency>
</dependencies>

Untuk metode instalasi lainnya, lihat Instal SDK SMQ untuk Java.

Buat antrian SMQ

Buat antrian untuk menerima notifikasi interupsi spot instans dari CloudMonitor.

  1. Masuk ke Konsol SMQ. Di panel navigasi sebelah kiri, pilih Queue Model > Queues.

  2. Di bilah navigasi atas, pilih wilayah. Pada halaman Queues, klik Create Queue.

  3. Pada panel Create Queue, konfigurasikan parameter yang diperlukan lalu klik OK.

image

Buat kebijakan langganan

Kebijakan langganan memberi tahu CloudMonitor ke mana notifikasi event harus didorong. Konfigurasikan kebijakan ini agar meneruskan event interupsi spot instans ke antrian yang baru saja Anda buat.

  1. Masuk ke Konsol CloudMonitor. Di panel navigasi sebelah kiri, pilih Event Center > Event Subscription.

  2. Pada tab Subscription Policy, klik Create Subscription Policy.

  3. Atur Subscription Type menjadi System Events.

    image

  4. Konfigurasikan Subscription Scope seperti yang ditunjukkan di bawah ini.

    image

  5. Di bawah Push and Integration, klik Add Channel, lalu klik Increase Channels. Pilih antrian SMQ yang telah Anda buat dan ikuti petunjuk di layar untuk menyelesaikan konfigurasi saluran dorong. Untuk detail opsi saluran dorong, lihat Kelola saluran dorong. Untuk daftar lengkap parameter langganan, lihat Kelola langganan event.

Simulasikan event interupsi

Interupsi spot instans bersifat tidak dapat diprediksi, sehingga CloudMonitor menyediakan alat Debug Event Subscription untuk mensimulasikannya selama pengembangan.

  1. Pada tab Subscription Policy, klik Debug Event Subscription.

  2. Pada panel Create Event Debugging, atur Products menjadi Elastic Compute Service (ECS) dan Name menjadi Instance:PreemptibleInstanceInterruption. Sistem secara otomatis menghasilkan muatan JSON. Perbarui nilai placeholder dengan informasi instans aktual Anda:

    • Ganti <Alibaba Cloud account ID> dengan ID akun Alibaba Cloud Anda.

    • Ganti <resource-id> dan <instanceId> dengan ID spot instans tersebut.

    • Ganti <Region ID> dengan ID wilayah spot instans tersebut.

    FieldDescription
    nameJenis event. Periksa field ini untuk memastikan pesan tersebut merupakan event interupsi.
    content.instanceIdID spot instans yang akan ditarik kembali.
    content.actionTindakan yang diambil. delete berarti instans akan dihentikan dan ditarik kembali.
    levelTingkat keparahan event. Misalnya, WARN menunjukkan adanya event interupsi.
    {
        "product": "ECS",
        "resourceId": "acs:ecs:cn-shanghai:<Alibaba Cloud account ID>UID:instance/<resource-id>",
        "level": "WARN",
        "instanceName": "instanceName",
        "regionId": "<Region ID>",
        "groupId": "0",
        "name": "Instance:PreemptibleInstanceInterruption",
        "content": {
            "instanceId": "<instanceId>",
            "instanceName": "wor***b73",
            "action": "delete"
        },
        "status": "Normal"
    }

    Field utama dalam muatan event:

  3. Klik OK. CloudMonitor mengirimkan peringatan simulasi ke antrian SMQ Anda.

Ambil dan tanggapi pesan

Contoh Java berikut menunjukkan cara mengambil notifikasi interupsi dari SMQ dan meresponsnya. Contoh ini menggunakan tugas konversi gambar ke skala abu-abu sebagai pengganti beban kerja nyata — pola yang sama berlaku untuk pekerjaan apa pun yang dapat diinterupsi.

Kode contoh lengkap

import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.common.utils.ServiceSettings;
import com.aliyun.mns.model.Message;
import org.json.JSONObject;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Pemroses gambar yang dapat diinterupsi dan mendukung shutdown yang mulus saat spot instans ditarik kembali.
 *
 * Perilaku utama:
 * - Menyimpan progres setiap 50 baris diproses (mekanisme checkpoint)
 * - Merespons segera ketika event interupsi diterima dari SMQ
 * - Menulis hasil parsial ke partial_output.jpg saat terjadi interupsi
 */
public class InterruptibleImageProcessor implements Runnable {

    // AtomicBoolean untuk kontrol status aman thread
    private final AtomicBoolean running = new AtomicBoolean(true);
    // Menyimpan gambar yang sedang diproses
    private BufferedImage processedImage;
    // Progres pemrosesan (0-100)
    private int progress;

    /**
     * Mengonversi gambar ke skala abu-abu menggunakan rata-rata tertimbang ITU-R BT.601:
     * Gray = 0.30*R + 0.59*G + 0.11*B
     *
     * Menyimpan progres setiap 50 baris untuk meminimalkan kehilangan data saat interupsi.
     */
    public void convertToGrayScale(File inputFile, File outputFile) throws Exception {
        BufferedImage original = ImageIO.read(inputFile);
        int width = original.getWidth();
        int height = original.getHeight();
        processedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

        for (int y = 0; y < height && running.get(); y++) {
            for (int x = 0; x < width; x++) {
                // Periksa flag interupsi thread pada setiap piksel
                if (Thread.interrupted()) {
                    throw new InterruptedException("Pemrosesan gambar diinterupsi");
                }
                // Pisahkan saluran ARGB
                int rgb = original.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;  // Saluran merah
                int g = (rgb >> 8) & 0xFF;   // Saluran hijau
                int b = rgb & 0xFF;           // Saluran biru
                // Terapkan rata-rata tertimbang
                int gray = (int)(0.3 * r + 0.59 * g + 0.11 * b);
                // Bangun kembali RGB dari nilai skala abu-abu
                processedImage.setRGB(x, y, (gray << 16) | (gray << 8) | gray);
                // Perbarui persentase progres (catatan: pembagian integer)
                progress = (y * width + x) * 100 / (width * height);
            }
            // Simpan checkpoint setiap 50 baris
            if (y % 50 == 0) {
                saveProgress(outputFile);
            }
        }
        // Simpan hasil akhir
        ImageIO.write(processedImage, "jpg", outputFile);
    }

    /**
     * Menyimpan status pemrosesan saat ini ke file sementara.
     * Menggunakan pendekatan silent-fail agar proses penyimpanan itu sendiri tidak terganggu.
     */
    private void saveProgress(File outputFile) {
        try {
            // Tulis ke file sementara agar tidak menimpa output akhir
            ImageIO.write(processedImage, "jpg", new File("partial_output.jpg"));
        } catch (Exception e) {
            System.err.println("Penyimpanan otomatis gagal: " + e.getMessage());
        }
    }

    /**
     * Titik masuk thread.
     * Saat diinterupsi: menyimpan progres saat ini, lalu menginterupsi kembali thread
     * untuk mempertahankan semantik interupsi bagi pemanggil.
     */
    @Override
    public void run() {
        try {
            convertToGrayScale(new File("input.jpg"), new File("output.jpg"));
            Thread.sleep(5000); // Mensimulasikan tugas berdurasi panjang
            System.out.println("Pemrosesan gambar selesai");
        } catch (InterruptedException e) {
            System.out.println("Pemrosesan diinterupsi pada " + progress + "%");
            saveProgress(new File("partial_output.jpg"));
            Thread.currentThread().interrupt(); // Pulihkan status interupsi
        } catch (Exception e) {
            System.err.println("Menangani error: " + e.getMessage());
        }
    }

    /**
     * Memberi sinyal kepada pemroses untuk berhenti setelah baris saat ini selesai.
     */
    public void stop() {
        running.set(false);
    }

    /**
     * Metode utama: menjalankan pemroses gambar, melakukan polling SMQ untuk event interupsi,
     * dan mematikan pemroses secara mulus saat event tersebut diterima.
     */
    public static void main(String[] args) throws InterruptedException {
        // Inisialisasi klien SMQ menggunakan kredensial dari variabel lingkungan
        CloudAccount account = new CloudAccount(
                ServiceSettings.getMNSAccessKeyId(),
                ServiceSettings.getMNSAccessKeySecret(),
                ServiceSettings.getMNSAccountEndpoint());
        MNSClient client = account.getMNSClient();

        // Jalankan tugas pemrosesan gambar di thread latar belakang
        InterruptibleImageProcessor processor = new InterruptibleImageProcessor();
        Thread processThread = new Thread(processor);
        processThread.start();

        try {
            // Lakukan polling terhadap antrian SMQ untuk notifikasi interupsi
            CloudQueue queue = client.getQueueRef("spot-interruption");
            Message popMsg = queue.popMessage();

            if (popMsg != null) {
                // Isi pesan dari SMQ dikodekan Base64 secara default
                System.out.println("Isi pesan mentah: " + popMsg.getMessageBodyAsRawString());

                // Dekode dan uraikan muatan JSON
                byte[] decodedBytes = Base64.getDecoder().decode(popMsg.getMessageBodyAsRawString());
                String decodedString = new String(decodedBytes);
                System.out.println("Pesan terdekripsi: " + decodedString);

                JSONObject json = new JSONObject(decodedString);
                String name = json.getString("name");

                // Periksa apakah ini event interupsi spot instans
                if ("Instance:PreemptibleInstanceInterruption".equals(name)) {
                    System.out.println("Spot instans akan segera ditarik kembali. Mematikan sistem...");

                    // Beri sinyal kepada pemroses untuk berhenti dan tunggu hingga selesai
                    processor.stop();
                    processThread.interrupt();
                    processThread.join();
                    System.out.println("Shutdown selesai");

                    // Hapus pesan agar tidak diproses ulang
                    queue.deleteMessage(popMsg.getReceiptHandle());
                }
            }
        } catch (Exception e) {
            System.out.println("Error tak terduga: ");
            e.printStackTrace();
        }

        client.close();
    }
}
Contoh ini menggunakan tugas konversi gambar ke skala abu-abu untuk menunjukkan pola penanganan interupsi. Gantilah logika pemrosesan gambar dengan beban kerja Anda sendiri. Pola inti — penyimpanan checkpoint, flag stop atomik, dan penghapusan pesan SMQ setelah ditangani — berlaku untuk pekerjaan berdurasi panjang apa pun pada spot instans.

Langkah berikutnya

  • Untuk membuat Snapshot disk sebelum instans ditarik kembali, lihat CreateSnapshot.

  • Untuk membuat gambar kustom dari instans sebelum penarikan kembali, lihat CreateImage.

  • Untuk strategi menyimpan dan memulihkan data yang tersimpan di spot instans, lihat Retain and restore data.

Referensi