Panduan Lengkap Spring Boot 4 · Pelajaran

Pengehadan Kadar, Percubaan Semula dan Pengehad Masa

Gabungkan pengehad kadar, percubaan semula dan tamat masa untuk membentuk beban serta membendung kegagalan berantai.

Pelajaran 3 daripada 413 langkah

Pengehadan Kadar, Percubaan Semula dan Pengehad Masa ialah pelajaran Panduan Lengkap Spring Boot 4 percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Panduan Lengkap Spring Boot 4, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Tiga Pelaras untuk Membentuk Beban

Pemutus litar menghentikan panggilan kepada kebergantungan yang tidak berfungsi, tetapi itu hanyalah satu alat dalam set alat ketahanan. Untuk membentuk beban masuk dan membendung kegagalan berantai, anda menggabungkan tiga primitif Resilience4j yang lain:

  • RateLimiter — mengehadkan bilangan panggilan bagi setiap tetingkap masa yang dibenarkan untuk bermula. Pemanggil berlebihan akan menunggu atau ditolak.
  • Retry — memanggil semula panggilan yang gagal beberapa kali dalam had tertentu, sebaik-baiknya dengan penangguhan, untuk mengharungi ralat sementara.
  • TimeLimiter — mengehadkan tempoh satu panggilan boleh berjalan sebelum dibatalkan, sekali gus membebaskan utas dan mengehadkan kependaman hujung ekor.

Apabila digunakan bersama, ciri ini melindungi anda (jangan membebankan perkhidmatan sendiri) dan sistem hiliran (jangan menghujani kebergantungan yang sedang bermasalah).

Menambahkan Resilience4j pada Spring Boot 4

Spring Boot 4 mengintegrasikan Resilience4j melalui pemula Spring Cloud Circuit Breaker / resilience4j-spring-boot3, yang mendedahkan aspek berasaskan anotasi untuk setiap primitif.

Tambahkan pemula dan sokongan AOP supaya anotasi tersebut diterapkan:

  • resilience4j-spring-boot3 menyediakan aspek RateLimiter, Retry, TimeLimiter, CircuitBreaker dan Bulkhead.
  • spring-boot-starter-aop diperlukan — anotasi dilaksanakan sebagai nasihat AOP.
  • Metrik mengalir ke Micrometer secara automatik apabila Actuator tersedia.
<dependencies>
  <dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>
</dependencies>

RateLimiter: Mengehadkan Panggilan bagi Setiap Tetingkap

RateLimiter membahagikan masa kepada tempoh penyegaran. Setiap tempoh memberikan bilangan permit yang tetap. Pemanggil yang mendapati tiada permit tersedia akan menunggu sehingga timeoutDuration; jika masih tiada permit, panggilan itu gagal dengan pantas menggunakan RequestNotPermitted.

Konfigurasikan tika dalam application.yml di bawah resilience4j.ratelimiter:

  • limitForPeriod — permit yang diberikan pada setiap tempoh penyegaran.
  • limitRefreshPeriod — kekerapan kiraan permit ditetapkan semula.
  • timeoutDuration — tempoh pemanggil disekat untuk menunggu permit sebelum ditolak.
resilience4j:
  ratelimiter:
    instances:
      pricingApi:
        limitForPeriod: 50
        limitRefreshPeriod: 1s
        timeoutDuration: 200ms
        registerHealthIndicator: true

Menggunakan @RateLimiter

Anotasikan kaedah yang memanggil sumber yang dilindungi. name mesti sepadan dengan tika YAML. Apabila had melebihi dan tiada permit dibebaskan dalam tempoh timeoutDuration, Resilience4j melontarkan RequestNotPermitted — halakan keadaan ini kepada kaedah sandaran supaya pelanggan menerima 429 yang dikendalikan dengan baik, bukannya jejak tindanan.

Keputusan utama: RateLimiter mengehadkan panggilan keluar anda. Ia tidak memperlahankan trafik HTTP masuk dengan sendirinya — gabungkannya dengan kaedah sandaran yang menandakan tekanan balik.

@Service
public class PricingClient {

    private final RestClient restClient;

    public PricingClient(RestClient restClient) {
        this.restClient = restClient;
    }

    @RateLimiter(name = "pricingApi", fallbackMethod = "throttled")
    public Quote fetchQuote(String symbol) {
        return restClient.get()
                .uri("/quotes/{symbol}", symbol)
                .retrieve()
                .body(Quote.class);
    }

    private Quote throttled(String symbol, RequestNotPermitted ex) {
        throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS,
                "Pricing rate limit exceeded, retry shortly");
    }
}

Retry: Mengharungi Kegagalan Sementara

Retry memanggil semula panggilan yang gagal sehingga maxAttempts kali. Ia hanya sesuai untuk kerosakan sementara — tetapan semula sambungan, 503 dan tamat masa singkat — serta hanya selamat pada operasi idempoten. Cuba semula POST yang tidak idempoten boleh menyebabkan pelanggan dicaj dua kali.

Gunakan penangguhan eksponen untuk mengelakkan gelombang cuba semula yang serentak, dan nyatakan dengan jelas pengecualian yang perlu dicuba semula serta yang perlu dihentikan serta-merta:

  • retryExceptions — hanya pengecualian ini mencetuskan cubaan semula.
  • ignoreExceptions — pengecualian ini dihentikan serta-merta (contohnya ralat pelanggan 4xx).
  • enableExponentialBackoff dengan pengganda menyebarkan jarak antara cubaan.
resilience4j:
  retry:
    instances:
      pricingApi:
        maxAttempts: 3
        waitDuration: 200ms
        enableExponentialBackoff: true
        exponentialBackoffMultiplier: 2
        retryExceptions:
          - java.io.IOException
          - org.springframework.web.client.HttpServerErrorException
        ignoreExceptions:
          - org.springframework.web.client.HttpClientErrorException

Penangguhan Eksponen dengan Jitter secara Konsep

Penangguhan eksponen menggandakan tempoh menunggu selepas setiap cubaan: 200ms, 400ms, 800ms... Namun, jika ribuan pelanggan gagal pada saat yang sama, semuanya akan menangguh secara serentak dan berkumpul semula — gelombang cuba semula. Penambahan jitter (tempoh menunggu rawak) menyahsegerakkan kesemuanya.

Atur cara kendiri ini memodelkan jadual menunggu supaya anda dapat melihat taburan kelewatan penangguhan-dengan-jitter yang boleh dijalankan oleh hakim dalam talian tanpa rangka kerja:

import java.util.concurrent.ThreadLocalRandom;

public class BackoffDemo {
    static long backoffWithJitter(int attempt, long baseMillis, double multiplier) {
        double exp = baseMillis * Math.pow(multiplier, attempt - 1);
        long jitter = ThreadLocalRandom.current().nextLong((long) (exp / 2) + 1);
        return (long) (exp / 2) + jitter; // half fixed, half random
    }

    public static void main(String[] args) {
        for (int attempt = 1; attempt <= 4; attempt++) {
            long wait = backoffWithJitter(attempt, 200, 2.0);
            System.out.println("Attempt " + attempt + " -> wait ~" + wait + "ms");
        }
    }
}

Menggunakan @Retry

Letakkan @Retry pada kaedah yang sama. Susunan penting apabila anotasi digabungkan: Resilience4j menggunakan aspek mengikut susunan Retry → CircuitBreaker → RateLimiter → TimeLimiter → Bulkhead (paling luar ke paling dalam), jadi Retry membungkus panggilan yang dihadkan kadar dan setiap cubaan memperoleh semula permit.

Kaedah sandaran menerima pengecualian terakhir selepas semua cubaan habis:

@Service
public class PricingClient {

    @Retry(name = "pricingApi")
    @RateLimiter(name = "pricingApi", fallbackMethod = "throttled")
    public Quote fetchQuote(String symbol) {
        return restClient.get()
                .uri("/quotes/{symbol}", symbol)
                .retrieve()
                .body(Quote.class);
    }

    private Quote throttled(String symbol, Throwable ex) {
        // Returns a last-known-good or default after retries + limit exhausted
        return Quote.unavailable(symbol);
    }
}

TimeLimiter: Mengehadkan Kependaman Hujung Ekor

TimeLimiter mengehadkan tempoh satu panggilan tak segerak boleh berjalan. Ia hanya berfungsi dengan future — kaedah mesti memulangkan CompletableFuture (atau jenis tak segerak lain yang disokong) supaya Resilience4j boleh membatalkannya apabila tarikh akhir berlalu.

Ini ialah penawar kepada kebergantungan yang perlahan: cuba semula mengendalikan kegagalan, tetapi panggilan yang hanya tergantung selama 30 saat akan menghabiskan himpunan utas anda. TimeLimiter menukar keadaan tergantung itu menjadi TimeoutException dengan pantas.

  • timeoutDuration — tarikh akhir bagi setiap panggilan.
  • cancelRunningFuture — menyampuk tugasan yang sedang berjalan apabila tamat masa untuk membebaskan utasnya.
resilience4j:
  timelimiter:
    instances:
      pricingApi:
        timeoutDuration: 2s
        cancelRunningFuture: true

Menggunakan @TimeLimiter pada Kaedah Tak Segerak

@TimeLimiter memerlukan kaedah memulangkan CompletableFuture. Tanpa jenis pemulangan tak segerak, aspek tersebut tidak melakukan apa-apa secara senyap. Gabungkannya dengan CircuitBreaker supaya tamat masa berulang akhirnya membuka pemutus litar dan menghentikan pembaziran usaha.

Perhatikan bahawa kaedah sandaran juga memulangkan CompletableFuture — tandatangannya mesti sepadan dengan jenis pemulangan kaedah yang dilindungi:

@Service
public class PricingClient {

    @TimeLimiter(name = "pricingApi")
    @CircuitBreaker(name = "pricingApi", fallbackMethod = "timedOut")
    public CompletableFuture<Quote> fetchQuoteAsync(String symbol) {
        return CompletableFuture.supplyAsync(() ->
                restClient.get()
                        .uri("/quotes/{symbol}", symbol)
                        .retrieve()
                        .body(Quote.class));
    }

    private CompletableFuture<Quote> timedOut(String symbol, Throwable ex) {
        return CompletableFuture.completedFuture(Quote.unavailable(symbol));
    }
}

Menyusun Ketiga-tiganya dengan Betul

Apabila ketiga-tiganya disusun bersama, susunan aspek menentukan tingkah laku. Susunan hiasan lalai yang didokumenkan oleh Resilience4j, dari luar ke dalam, ialah:

Retry( CircuitBreaker( RateLimiter( TimeLimiter( Bulkhead( call ) ) ) ) )

  • Retry paling luar supaya cubaan semula menjalankan semula keseluruhan rantaian yang dilindungi, memeriksa semula pemutus litar dan memperoleh semula permit had kadar pada setiap cubaan.
  • TimeLimiter di bahagian dalam supaya setiap cubaan individu mempunyai tarikh akhirnya sendiri — cubaan semula bagi panggilan yang tamat masa mendapat jam baharu.
  • Meletakkan Retry di dalam RateLimiter akan menyebabkan satu panggilan logik menggunakan beberapa permit bagi setiap cubaan — biasanya tidak betul dan boleh menyebabkan pemanggil lain tidak mendapat giliran.

Dengan anotasi, anda tidak perlu menyusunnya secara manual; Resilience4j menguatkuasakan susunan ini melalui keutamaan aspek.

Memantau dan Melaraskan melalui Actuator

Anda tidak boleh melaraskan perkara yang tidak dapat dilihat. Dengan Actuator pada laluan kelas, setiap tika menerbitkan metrik Micrometer dan penunjuk kesihatan. Dedahkan penunjuk tersebut dan perhatikan isyarat utama:

  • resilience4j_ratelimiter_available_permissions — jika nilainya kekal sifar, anda sedang mengehadkan trafik sebenar; naikkan had atau tambah skala.
  • resilience4j_retry_calls yang ditag kind=successful_with_retry berbanding failed_with_retry — nilai failed-with-retry yang tinggi bermaksud cubaan semula tidak membantu; kerosakan itu bukan sementara.
  • resilience4j_timelimiter_calls yang ditag kind=timeout — peningkatan tamat masa menandakan kebergantungan semakin merosot sebelum pemutus litar terbuka.
management:
  endpoints:
    web:
      exposure:
        include: health, metrics, ratelimiters, retries
  metrics:
    tags:
      application: tracing-service
  health:
    ratelimiters:
      enabled: true

Semakan Pantas: Memilih Primitif yang Tepat

API penentuan harga hiliran kadangkala tergantung selama 30 saat atau lebih dan bukannya memulangkan ralat, lalu keadaan ini menghabiskan utas permintaan perkhidmatan anda. Primitif Resilience4j yang manakah paling langsung menangani mod kegagalan khusus ini?

Ulang Kaji: Membentuk Beban dan Membendung Kegagalan

Anda telah menggabungkan tiga primitif yang saling melengkapi untuk membentuk beban dan membendung kegagalan berantai:

  • RateLimiter mengehadkan bilangan panggilan bagi setiap tetingkap, dan menolak lebihan dengan RequestNotPermitted supaya anda tidak membebankan diri sendiri atau perkhidmatan hiliran.
  • Percubaan semula membantu mengatasi kegagalan sementara pada panggilan idempoten, menggunakan pengunduran eksponen bersama gegaran rawak untuk mengelakkan gelombang percubaan semula.
  • TimeLimiter mengehadkan kependaman ekor pada panggilan tak segerak (CompletableFuture), menukar keadaan tergantung kepada tamat masa yang pantas dan membebaskan bebenang.

Susun semuanya melalui anotasi; Resilience4j menguatkuasakan turutan Retry → CircuitBreaker → RateLimiter → TimeLimiter → Bulkhead supaya percubaan semula menjalankan semula seluruh rantaian yang dilindungi, manakala setiap percubaan mempunyai tarikh akhir tersendiri. Sentiasa sambungkan kaedah sandaran untuk kemerosotan perkhidmatan yang terkawal, dan pantau metrik Actuator/Micrometer untuk melaraskan had berdasarkan trafik sebenar.

Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
21
Pelajaran
84

Soalan Lazim

Adakah pelajaran “Pengehadan Kadar, Percubaan Semula dan Pengehad Masa” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Panduan Lengkap Spring Boot 4, termasuk “Pengehadan Kadar, Percubaan Semula dan Pengehad Masa”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pengehadan Kadar, Percubaan Semula dan Pengehad Masa”?

Gabungkan pengehad kadar, percubaan semula dan tamat masa untuk membentuk beban serta membendung kegagalan berantai. Anda berlatih Panduan Lengkap Spring Boot 4 menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Panduan Lengkap Spring Boot 4?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Panduan Lengkap Spring Boot 4 di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “Pengehadan Kadar, Percubaan Semula dan Pengehad Masa” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Panduan Lengkap Spring Boot 4 ini?

Ya. Setiap pelajaran Panduan Lengkap Spring Boot 4 menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Penyebaran Konteks dan Instrumentasi Rentang
  2. Pemutus Litar dan Pengasingan Sekat
  3. Pengehadan Kadar, Percubaan Semula dan Pengehad Masa
  4. Menghubungkaitkan Log, Metrik dan Jejak
← Kembali ke Panduan Lengkap Spring Boot 4