Ratpack dengan Hystrix

1. Perkenalan

Sebelumnya, kami telah menunjukkan cara membuat aplikasi berkinerja tinggi dan reaktif dengan Ratpack.

Pada artikel ini, kita akan melihat bagaimana mengintegrasikan Netflix Hystrix dengan aplikasi Ratpack.

Netflix Hystrix membantu mengontrol interaksi antara layanan terdistribusi dengan mengisolasi titik akses untuk menghentikan kegagalan berjenjang dan menyediakan opsi fallback untuk toleransi kesalahan. Ini dapat membantu kami membangun aplikasi yang lebih tangguh. Lihat pengantar kami ke Hystrix untuk tinjauan singkat.

Jadi, begitulah cara kami menggunakannya - kami akan menyempurnakan aplikasi Ratpack kami dengan fitur-fitur berguna ini dari Hystrix.

2. Ketergantungan Maven

Untuk menggunakan Hystrix dengan Ratpack, kita memerlukan dependensi ratpack-hystrix di proyek pom.xml :

 io.ratpack ratpack-hystrix 1.4.6 

Versi terbaru dari ratpack-hystrix dapat ditemukan di sini. Ratpack-hystrix mencakup ratpack-core dan hystrix-core.

Untuk menggunakan fitur reaktif Ratpack, kita juga memerlukan ratpack-rx:

 io.ratpack ratpack-rx 1.4.6 

Versi terbaru dari ratpack-rx dapat ditemukan di sini.

3. Melayani Dengan Perintah Hystrix

Saat menggunakan Hystrix, layanan yang mendasarinya biasanya dibungkus dalam HystrixCommand atau HystrixObservableCommand . Hystrix mendukung pelaksanaan Perintah ini dengan cara sinkron, asinkron dan reaktif. Di antaranya, hanya reaktif yang nonblocking dan direkomendasikan secara resmi.

Dalam contoh berikut, kami akan membuat beberapa titik akhir yang mengambil profil dari Github REST API.

3.1. Eksekusi Perintah Reaktif

Pertama, mari buat layanan backend reaktif dengan Hystrix:

public class HystrixReactiveHttpCommand extends HystrixObservableCommand { //... @Override protected Observable construct() { return RxRatpack.observe(httpClient .get(uri, r -> r.headers(h -> h.add("User-Agent", "Baeldung HttpClient"))) .map(res -> res.getBody().getText())); } @Override protected Observable resumeWithFallback() { return Observable.just("eugenp's reactive fallback profile"); } }

Di sini, HttpClient reaktif Ratpack digunakan untuk membuat permintaan GET. The HystrixReactiveHttpCommand dapat melakukan sebagai handler reaktif:

chain.get("rx", ctx -> new HystrixReactiveHttpCommand( ctx.get(HttpClient.class), eugenGithubProfileUri, timeout) .toObservable() .subscribe(ctx::render));

Titik akhir dapat diverifikasi dengan tes berikut:

@Test public void whenFetchReactive_thenGotEugenProfile() { assertThat(appUnderTest.getHttpClient().getText("rx"), containsString("www.baeldung.com")); }

3.2. Eksekusi Perintah Asinkron

Eksekusi asinkron dari HystrixCommand mengantre perintah di kumpulan utas dan mengembalikan Masa Depan :

chain.get("async", ctx -> ctx.render( new HystrixAsyncHttpCommand(eugenGithubProfileUri, timeout) .queue() .get()));

The HystrixAsyncHttpCommand terlihat seperti:

public class HystrixAsyncHttpCommand extends HystrixCommand { //... @Override protected String run() throws Exception { return EntityUtils.toString(HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setDefaultHeaders(Collections.singleton( new BasicHeader("User-Agent", "Baeldung Blocking HttpClient"))) .build().execute(new HttpGet(uri)).getEntity()); } @Override protected String getFallback() { return "eugenp's async fallback profile"; } }

Di sini kami menggunakan HttpClient yang memblokir daripada yang nonblocking karena kami ingin Hystrix mengontrol waktu tunggu eksekusi dari perintah yang sebenarnya sehingga kami tidak perlu menanganinya sendiri saat mendapatkan respons dari Future . Ini juga memungkinkan Hystrix untuk mengembalikan atau menyimpan permintaan kami.

Eksekusi asinkron juga menghasilkan hasil yang diharapkan:

@Test public void whenFetchAsync_thenGotEugenProfile() { assertThat(appUnderTest.getHttpClient().getText("async"), containsString("www.baeldung.com")); }

3.3. Eksekusi Perintah Sinkron

Eksekusi sinkron menjalankan perintah secara langsung di utas saat ini:

chain.get("sync", ctx -> ctx.render( new HystrixSyncHttpCommand(eugenGithubProfileUri, timeout).execute()));

Implementasi HystrixSyncHttpCommand hampir identik dengan HystrixAsyncHttpCommand kecuali kita memberikan hasil fallback yang berbeda. Saat tidak mundur, perilakunya sama dengan eksekusi reaktif dan asinkron:

@Test public void whenFetchSync_thenGotEugenProfile() { assertThat(appUnderTest.getHttpClient().getText("sync"), containsString("www.baeldung.com")); }

4. Metrik

Dengan mendaftarkan modul Guice - HystrixModule ke dalam registri Ratpack, kita dapat melakukan streaming metrik cakupan permintaan dan mengekspos aliran peristiwa melalui titik akhir GET :

serverSpec.registry( Guice.registry(spec -> spec.module(new HystrixModule().sse()))) .handlers(c -> c.get("hystrix", new HystrixMetricsEventStreamHandler()));

The HystrixMetricsEventStreamHandler membantu aliran Hystrix metrik dalam text / event-stream Format, sehingga kita bisa memantau metrik di Hystrix Dashboard .

Kami dapat menyiapkan dasbor Hystrix mandiri, dan menambahkan aliran acara Hystrix kami ke daftar monitor untuk melihat bagaimana kinerja aplikasi Ratpack kami:

Setelah beberapa permintaan ke aplikasi Ratpack kami, kami dapat melihat perintah terkait Hystrix di dasbor.

4.1. Dibawah tenda

Di HystrixModule , Strategi Konkurensi Hystrix terdaftar dengan Hystrix melalui HystrixPlugin untuk mengelola konteks permintaan dengan registri Ratpack. Ini menghilangkan kebutuhan untuk menginisialisasi konteks permintaan Hystrix sebelum setiap permintaan dimulai.

public class HystrixModule extends ConfigurableModule { //... @Override protected void configure() { try { HystrixPlugins.getInstance().registerConcurrencyStrategy( new HystrixRegistryBackedConcurrencyStrategy()); } catch (IllegalStateException e) { //... } } //... }

5. Kesimpulan

Dalam artikel singkat ini, kami telah menunjukkan bagaimana Hystrix dapat diintegrasikan ke dalam Ratpack dan cara mendorong metrik dari aplikasi Ratpack kami ke Dasbor Hystrix untuk tampilan yang lebih baik dari kinerja aplikasi.

Seperti biasa, implementasi penuh dapat ditemukan di proyek Github.