全部产品
Search
文档中心

Elastic Compute Service:Mendeteksi dan menanggapi insiden interupsi instans spot dengan menggunakan SMQ

更新时间:Jul 06, 2025

Instans Spot dapat mengalami interupsi. Jika bisnis Anda sensitif terhadap interupsi instans, segera deteksi interupsi instans spot dan tanggapi peristiwa tersebut secara tepat guna meminimalkan dampak bisnis. Topik ini memberikan contoh penggunaan Simple Message Queue (SMQ), sebelumnya dikenal sebagai Message Service (MNS), untuk mendeteksi dan menanggapi peristiwa interupsi instans spot.

Alur Kerja

Persiapan

  1. Buat sepasang AccessKey.

    Buat sepasang AccessKey untuk Pengguna Resource Access Management (RAM). Akun Alibaba Cloud memiliki semua izin pada sumber daya. Jika pasangan AccessKey akun Alibaba Cloud Anda bocor, sumber daya Anda akan terpapar risiko. Kami sarankan menggunakan pasangan AccessKey dari pengguna RAM. Untuk informasi lebih lanjut tentang cara membuat pasangan AccessKey, lihat Buat Pasangan AccessKey.

  2. Berikan Izin kepada Pengguna RAM.

    Berikan pengguna RAM izin untuk melakukan operasi pada sumber daya terkait SMQ. Kode sampel yang disediakan dalam topik ini mengonsumsi pesan dari SMQ. Tabel berikut menjelaskan izin pada SMQ yang dapat Anda berikan.

    Layanan cloud

    Kebijakan

    SMQ, sebelumnya MNS

    AliyunMNSFullAccess

  3. Konfigurasikan Kredensial Akses dan Titik Akhir.

    Kode sampel dalam topik ini membaca kredensial akses dan titik akhir dari variabel lingkungan sistem:

  4. Instal SDK SMQ.

    Dapatkan SDK SMQ untuk Java. Dalam contoh ini, SDK SMQ untuk Java diinstal dengan menambahkan dependensi Maven. Untuk informasi tentang metode instalasi lainnya, lihat Instal SDK SMQ untuk Java.

    Kode sampel berikut memberikan contoh cara menambahkan dependensi Maven:

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

Prosedur

  1. Buat SMQ.

    Buat SMQ untuk menerima notifikasi interupsi instans spot yang dikirim oleh CloudMonitor.

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

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

    3. Di panel Create Queue, ikuti petunjuk di layar untuk mengonfigurasi parameter yang diperlukan dan klik OK.

      image

  2. Buat Kebijakan Langganan.

    CloudMonitor memantau peristiwa interupsi instans spot secara real-time. Jika terjadi peringatan peristiwa, CloudMonitor mendorong notifikasi interupsi melalui saluran dorongan yang ditentukan dalam kebijakan langganan.

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

    2. Pada tab Subscription Policy, klik Create Subscription Policy dan konfigurasikan parameter yang diperlukan.

      Contoh ini hanya menjelaskan parameter utama yang digunakan untuk berlangganan peristiwa interupsi instans spot. Anda dapat menentukan parameter berdasarkan kebutuhan bisnis Anda. Untuk informasi lebih lanjut, lihat Kelola Langganan Peristiwa.

      • Subscription Type: Pilih System Events.

        image

      • Subscription Scope: Tentukan parameter seperti yang ditunjukkan pada gambar berikut.

        image

      • Push and Integration: Klik Add Channel. Di kotak dialog yang muncul, klik Increase Channels. Di kotak dialog yang muncul, pilih SMQ yang Anda buat di Langkah 1 dan konfigurasikan parameter lainnya dengan mengikuti petunjuk di layar. Untuk informasi tentang saluran dorongan, lihat Kelola Saluran Dorongan.

  3. Simulasikan Peristiwa Interupsi.

    Peristiwa interupsi instans spot adalah peristiwa yang dipicu. Saat Anda mengembangkan penanganan peristiwa interupsi untuk instans spot, Anda tidak dapat men-debug kode. Anda dapat menggunakan Debug Event Subscription untuk mensimulasikan peristiwa interupsi instans spot.

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

    2. Di panel Create Event Debugging, atur Products ke Elastic Compute Service (ECS) dan Name ke Instance:PreemptibleInstanceInterruption.

      Sistem secara otomatis menghasilkan konten debugging dalam format JSON. Ganti informasi sumber daya dalam file JSON dengan informasi tentang instans spot yang ingin Anda simulasikan untuk peristiwa interupsi.

      • Ganti ID akun Alibaba Cloud dengan ID akun Alibaba Cloud Anda.

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

      • Ganti <region ID> dengan ID wilayah instans spot.

        {
            "product": "ECS",
            "resourceId": "acs:ecs:cn-shanghai:<ID akun Alibaba Cloud>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"
        }
    3. Klik OK. Pesan yang menunjukkan bahwa operasi berhasil muncul. CloudMonitor secara otomatis mengirimkan notifikasi peringatan ke SMQ.

  4. Tarik dan Tanggapi Pesan.

    Simulasikan penanganan peristiwa interupsi untuk menarik pesan notifikasi interupsi instans spot dari SMQ. Anda juga dapat menambahkan logika penanganan bisnis yang sesuai berdasarkan kebutuhan bisnis Anda. Kode sampel berikut memberikan contoh cara menggunakan penanganan konversi gambar skala abu-abu untuk menanggapi dan menangani peristiwa interupsi:

    1. Gunakan tugas thread untuk mensimulasikan penanganan konversi gambar skala abu-abu.

      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;
      
      /**
       * Kelas implementasi untuk pemroses gambar yang dapat diinterupsi yang mendukung konversi skala abu-abu.
       * Mekanisme deteksi interupsi berdasarkan variabel atomik dan flag interupsi thread.
       * Fitur:
       * 1. Lakukan pemrosesan per-chunk untuk menyimpan kemajuan secara otomatis.
       * 2. Tanggapi segera peristiwa interupsi instans spot.
       * 3. Hasilkan file yang berisi hasil parsial setelah peristiwa interupsi instans spot terjadi.
       */
      public class InterruptibleImageProcessor implements Runnable {
          /**
           * Gunakan nilai boolean atomik untuk kontrol status yang aman-thread.
           */
          private final AtomicBoolean running = new AtomicBoolean(true);
          /**
           * Simpan data gambar yang sedang diproses.
           */
          private BufferedImage processedImage;
          /**
           * Kemajuan pemrosesan dalam persentase. Nilai valid: 0 hingga 100.
           */
          private int progress;
          /**
           * Titik masuk eksekusi thread.
           * **Logika penanganan interupsi**:
           * 1. Simpan kemajuan saat ini setelah sistem menangkap pengecualian interupsi.
           * 2. Kembalikan thread ke keadaan saat interupsi terjadi untuk mempertahankan semantik interupsi.
           */
          @Override
          public void run() {
              try {
                  convertToGrayScale(new File("input.jpg"), new File("output.jpg"));
                  // Simulasikan peristiwa interupsi saat instans spot berjalan.
                  Thread.sleep(5000); 
                  System.out.println("Pemrosesan gambar selesai");
              } catch (InterruptedException e) {
                  System.out.println("Pemrosesan diinterupsi, dan kemajuan disimpan ke" + progress + "%");
                  saveProgress(new File("partial_output.jpg"));
                  Thread.currentThread().interrupt(); // Kembalikan thread ke keadaan saat thread diinterupsi.
              } catch (Exception e) {
                  System.err.println("Penanganan kesalahan: " + e.getMessage());
              }
          }
      
          /**
           * Metode untuk memicu interupsi eksternal
           * **Mekanisme kolaborasi**:
           * Periksa dua kali untuk interupsi berdasarkan flag interupsi thread.
           */
          public void stop() {
              running.set(false);
          }
      }
      
    2. Metode konversi gambar skala abu-abu.

      /**
       * Konversikan gambar yang Anda input menjadi gambar skala abu-abu dan simpan gambar tersebut.
       * @param inputFile Objek file gambar asli.
       * @param outputFile Objek file keluaran.
       * @throws Exception Anomali I/O dan pengecualian interupsi termasuk.
       *
       * **Deskripsi algoritma**:
       * Gunakan nilai rata-rata tertimbang dan koefisien yang dirancang berdasarkan kecerahan persepsi cahaya merah, hijau, dan biru dalam rumus berikut untuk mengonversi gambar menjadi skala abu-abu:
       * Gray = 0.30*R + 0.59*G + 0.11*B
       * Referensi: ITU-R Recommendation BT. 601.
       */
      public void convertToGrayScale(File inputFile, File outputFile) throws Exception {
          // Baca data gambar sumber.
          BufferedImage original = ImageIO.read(inputFile);
          int width = original.getWidth();
          int height = original.getHeight();
          // Buat buffer gambar skala abu-abu.
          processedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
      
          // Lakukan pemrosesan per-chunk untuk menyimpan kemajuan.
          for (int y = 0; y < height && running.get(); y++) {
              // Lakukan pemrosesan piksel demi piksel untuk gambar.
              for (int x = 0; x < width; x++) {
                  // Dalam deteksi interupsi pertama, periksa flag interupsi thread.
                  if (Thread.interrupted()) {
                      throw new InterruptedException("Pemrosesan gambar diinterupsi");
                  }
                  /* Algoritma inti untuk konversi gambar skala abu-abu * /
                  int rgb = original.getRGB(x, y);
                  // Dekomposisi saluran merah, hijau, dan biru (RGB) dalam format Alpha-Merah-Hijau-Biru (ARGB).
                  // Saluran merah.
                  int r = (rgb >> 16) & 0xFF;
                  // Saluran hijau.
                  int g = (rgb >> 8) & 0xFF;
                  // Saluran biru.
                  int b = rgb & 0xFF;
                  // Hitung nilai skala abu-abu menggunakan metode rata-rata tertimbang.
                  int gray = (int)(0.3 * r + 0.59 * g + 0.11 * b);
                  // Rekonstruksi nilai RGB dengan menyalin nilai skala abu-abu ke saluran merah, hijau, dan biru.
                  processedImage.setRGB(x, y, (gray << 16) | (gray << 8) | gray);
                  // Perbarui kemajuan dalam persentase. Perhatikan masalah pembagian integer, di mana nilai integer selain nilai desimal dikembalikan.
                  progress = (y * width + x) * 100 / (width * height);
              }
              // Simpan kemajuan secara otomatis setelah setiap 50 baris diproses berdasarkan mekanisme checkpoint.
              if (y % 50 == 0) {
                  saveProgress(outputFile);
              }
          }
          // Simpan hasil lengkap.
          ImageIO.write(processedImage, "jpg", outputFile);
      }
    3. Kemajuan pemrosesan gambar disimpan.

      /**
       * Simpan kemajuan pemrosesan ke file yang ditentukan.
       * @param outputFile Objek file keluaran.
       *
       * **Catatan**:
       * 1. Mekanisme fail-silent diimplementasikan untuk mencegah gangguan proses penyimpanan.
       * 2. File sementara bernama partial_output.jpg dihasilkan.
       */
      private void saveProgress(File outputFile) {
          try {
              // Gunakan nama file sementara untuk mencegah file utama tertimpa.
              ImageIO.write(processedImage, "jpg", new File("partial_output.jpg"));
          } catch (Exception e) {
              System.err.println("Auto-save gagal: " + e.getMessage());
          }
      }
    4. Uji pemrosesan respons.

      Saat program pemrosesan gambar uji sedang berjalan, sistem menerima peristiwa bahwa instans spot akan diinterupsi dan direklaim dan menanggapi peristiwa tersebut.

      /**
       * Metode pengujian utama
       * **Skenario pengujian**:
       * 1. Proses thread.
       * 2. Tarik pesan notifikasi peristiwa interupsi.
       * 3. Tunggu thread berhenti.
       */
      public static void main(String[] args) throws InterruptedException {
          // Inisialisasi akun MNSClient.
          CloudAccount account = new CloudAccount(
                  ServiceSettings.getMNSAccessKeyId(),
                  ServiceSettings.getMNSAccessKeySecret(),
                  ServiceSettings.getMNSAccountEndpoint());
          MNSClient client = account.getMNSClient();
          // Periksa apakah peristiwa interupsi terjadi pada instans spot.
          boolean isMatch = false;
          // Mulai program pemrosesan gambar.
          InterruptibleImageProcessor processor = new InterruptibleImageProcessor();
          Thread processThread = new Thread(processor);
          processThread.start();
          try{
              // Dapatkan pesan dari SMQ.
              CloudQueue queue = client.getQueueRef("spot-interruption");
              Message popMsg = queue.popMessage();
              if (popMsg != null){
                  // Secara default, isi pesan dikodekan dalam Base64.
                  System.out.println("message body: " + popMsg.getMessageBodyAsRawString());
                  // Lakukan dekode Base64.
                  byte[] decodedBytes = Base64.getDecoder().decode(popMsg.getMessageBodyAsRawString());
                  String decodedString = new String(decodedBytes);
                  System.out.println("message content: " + decodedString);
                  // Parse string JSON.
                  JSONObject json = new JSONObject(decodedString);
                  // Dapatkan nilai bidang nama peristiwa.
                  String name = json.getString("name");
                  isMatch = "Instance:PreemptibleInstanceInterruption".equals(name);
                  // Tanggapi peristiwa interupsi instans spot.
                  if(isMatch){
                      System.out.println("Instans spot akan diinterupsi dan direklaim.");
                      // Hentikan program pemrosesan gambar.
                      processor.stop();
                      processThread.interrupt();
                      System.out.println("Program dihentikan");
                      processThread.join();
                      // Hapus pesan.
                      queue.deleteMessage(popMsg.getReceiptHandle());
                  }
              }
          }catch (Exception e){
              System.out.println("Pengecualian tidak dikenal terjadi!");
              e.printStackTrace();
          }
          client.close();
      }

    Kode sampel:

    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;
    
    /**
     * Kelas implementasi untuk pemroses gambar yang dapat diinterupsi yang mendukung konversi skala abu-abu.
     * Mekanisme deteksi interupsi berdasarkan variabel atomik dan flag interupsi thread.
     * Fitur:
     * 1. Lakukan pemrosesan per-chunk untuk menyimpan kemajuan secara otomatis.
     * 2. Tanggapi segera peristiwa interupsi instans spot.
     * 3. Hasilkan file yang berisi hasil parsial setelah peristiwa interupsi instans spot terjadi.
     */
    public class InterruptibleImageProcessor implements Runnable {
        /**
         * Gunakan nilai boolean atomik untuk kontrol status yang aman-thread.
         */
        private final AtomicBoolean running = new AtomicBoolean(true);
        /**
         * Simpan data gambar yang sedang diproses.
         */
        private BufferedImage processedImage;
        /**
         * Kemajuan pemrosesan dalam persentase. Nilai valid: 0 hingga 100.
         */
        private int progress;
    
        /**
         * Konversikan gambar yang Anda input menjadi gambar skala abu-abu dan simpan gambar tersebut.
         * @param inputFile Objek file gambar asli.
         * @param outputFile Objek file keluaran.
         * @throws Exception Anomali I/O dan pengecualian interupsi termasuk.
         *
         * **Deskripsi algoritma**:
         * Gunakan nilai rata-rata tertimbang dan koefisien yang dirancang berdasarkan kecerahan persepsi cahaya merah, hijau, dan biru dalam rumus berikut untuk mengonversi gambar menjadi skala abu-abu:
         * Gray = 0.30*R + 0.59*G + 0.11*B
         * Referensi: ITU-R Recommendation BT. 601.
         */
        public void convertToGrayScale(File inputFile, File outputFile) throws Exception {
            // Baca data gambar sumber.
            BufferedImage original = ImageIO.read(inputFile);
            int width = original.getWidth();
            int height = original.getHeight();
            // Buat buffer gambar skala abu-abu.
            processedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
    
            // Lakukan pemrosesan per-chunk untuk menyimpan kemajuan.
            for (int y = 0; y < height && running.get(); y++) {
                // Lakukan pemrosesan piksel demi piksel untuk gambar.
                for (int x = 0; x < width; x++) {
                    // Dalam deteksi interupsi pertama, periksa flag interupsi thread.
                    if (Thread.interrupted()) {
                        throw new InterruptedException("Pemrosesan gambar diinterupsi");
                    }
                    /* Algoritma inti untuk konversi gambar skala abu-abu * /
                    int rgb = original.getRGB(x, y);
                    // Dekomposisi saluran RGB dalam format ARGB.
                    // Saluran merah.
                    int r = (rgb >> 16) & 0xFF;
                    // Saluran hijau.
                    int g = (rgb >> 8) & 0xFF;
                    // Saluran biru.
                    int b = rgb & 0xFF;
                    // Hitung nilai skala abu-abu menggunakan metode rata-rata tertimbang.
                    int gray = (int)(0.3 * r + 0.59 * g + 0.11 * b);
                    // Rekonstruksi nilai RGB dengan menyalin nilai skala abu-abu ke saluran merah, hijau, dan biru.
                    processedImage.setRGB(x, y, (gray << 16) | (gray << 8) | gray);
                    // Perbarui kemajuan dalam persentase. Perhatikan masalah pembagian integer, di mana nilai integer selain nilai desimal dikembalikan.
                    progress = (y * width + x) * 100 / (width * height);
                }
                // Simpan kemajuan secara otomatis setelah setiap 50 baris diproses berdasarkan mekanisme checkpoint.
                if (y % 50 == 0) {
                    saveProgress(outputFile);
                }
            }
            // Simpan hasil lengkap.
            ImageIO.write(processedImage, "jpg", outputFile);
        }
    
        /**
         * Simpan kemajuan pemrosesan ke file yang ditentukan.
         * @param outputFile Objek file keluaran.
         *
         * **Catatan**:
         * 1. Mekanisme fail-silent diimplementasikan untuk mencegah gangguan proses penyimpanan.
         * 2. File sementara bernama partial_output.jpg dihasilkan.
         */
        private void saveProgress(File outputFile) {
            try {
                // Gunakan nama file sementara untuk mencegah file utama tertimpa.
                ImageIO.write(processedImage, "jpg", new File("partial_output.jpg"));
            } catch (Exception e) {
                System.err.println("Auto save gagal: " + e.getMessage());
            }
        }
    
        /**
         * Titik masuk eksekusi thread.
         * **Logika penanganan interupsi**:
         * 1. Simpan kemajuan saat ini setelah sistem menangkap pengecualian interupsi.
         * 2. Kembalikan thread ke keadaan saat interupsi terjadi untuk mempertahankan semantik interupsi.
         */
        @Override
        public void run() {
            try {
                convertToGrayScale(new File("/Users/shaoberlin/Desktop/idea_workspace/aliyun/src/main/resources/input.jpg"), new File("output.jpg"));
                // Simulasikan peristiwa interupsi saat instans spot berjalan.
                Thread.sleep(5000); 
                System.out.println("Pemrosesan gambar selesai");
            } catch (InterruptedException e) {
                System.out.println("Pemrosesan diinterupsi, dan kemajuan disimpan ke" + progress + "%");
                saveProgress(new File("partial_output.jpg"));
                Thread.currentThread().interrupt(); // Kembalikan thread ke keadaan saat thread diinterupsi.
            } catch (Exception e) {
                System.err.println("Penanganan kesalahan:" + e.getMessage());
            }
        }
    
        /**
         * Metode untuk memicu interupsi eksternal
         * **Mekanisme kolaborasi**:
        Periksa dua kali untuk interupsi berdasarkan flag interupsi thread.
         */
        public void stop() {
            running.set(false);
        }
    
        /**
         * Metode pengujian utama
         * **Skenario pengujian**:
         * 1. Proses thread.
         * 2. Pemicu interupsi setelah 5.000 detik.
         * 3. Tunggu thread berhenti.
         */
        public static void main(String[] args) throws InterruptedException {
            // Inisialisasi akun MNSClient.
            CloudAccount account = new CloudAccount(
                    ServiceSettings.getMNSAccessKeyId(),
                    ServiceSettings.getMNSAccessKeySecret(),
                    ServiceSettings.getMNSAccountEndpoint());
            MNSClient client = account.getMNSClient();
            // Periksa apakah peristiwa interupsi terjadi pada instans spot.
            boolean isMatch = false;
            // Mulai program pemrosesan gambar.
            InterruptibleImageProcessor processor = new InterruptibleImageProcessor();
            Thread processThread = new Thread(processor);
            processThread.start();
            try{
                // Dapatkan pesan dari SMQ.
                CloudQueue queue = client.getQueueRef("spot-interruption");
                Message popMsg = queue.popMessage();
                if (popMsg != null){
                    // Secara default, isi pesan dikodekan dalam Base64.
                    System.out.println("message body: " + popMsg.getMessageBodyAsRawString());
                    // Lakukan dekode Base64.
                    byte[] decodedBytes = Base64.getDecoder().decode(popMsg.getMessageBodyAsRawString());
                    String decodedString = new String(decodedBytes);
                    System.out.println("message content: " + decodedString);
                    // Parse string JSON.
                    JSONObject json = new JSONObject(decodedString);
                    // Dapatkan nilai bidang nama peristiwa.
                    String name = json.getString("name");
                    isMatch = "Instance:PreemptibleInstanceInterruption".equals(name);
                    // Tanggapi peristiwa interupsi instans spot.
                    if(isMatch){
                        System.out.println("Instans spot akan diinterupsi dan direklaim.");
                        // Hentikan program pemrosesan gambar.
                        processor.stop();
                        processThread.interrupt();
                        System.out.println("Program dihentikan");
                        processThread.join();
                        // Hapus pesan.
                        queue.deleteMessage(popMsg.getReceiptHandle());
                    }
                }
            }catch (Exception e){
                System.out.println("Pengecualian tidak dikenal terjadi!");
                e.printStackTrace();
            }
            client.close();
        }
    }
    
Catatan
  • Jika logika bisnis melibatkan pembuatan snapshot, lihat CreateSnapshot.

  • Jika logika bisnis melibatkan pembuatan gambar kustom, lihat CreateImage.

Referensi

Jika Anda menyimpan data atau konfigurasi penting pada instans spot, kami sarankan Anda memahami metode pemulihan data instans spot dan mengonfigurasikan pengaturan yang diperlukan sebelumnya untuk mencegah kehilangan data. Untuk informasi lebih lanjut, lihat Pertahankan dan Pulihkan Data untuk Instans Spot.