1. Вступление
Ранее у нас была ссылка:/ratpack[показано], как создать высокопроизводительное и реактивное приложение с помощью Ratpack.
В этой статье мы рассмотрим, как интегрировать Netflix Hystrix с приложением Ratpack.
Netflix Hystrix помогает контролировать взаимодействие между распределенными сервисами, изолируя точки доступа, чтобы остановить каскадные сбои, и предоставляя варианты возврата для отказоустойчивости. Это может помочь нам создать более гибкое приложение. Посмотрите нашу ссылку:/Введение в Hystrix[Введение в Hystrix]для быстрого обзора.
Итак, вот как мы будем его использовать - мы собираемся улучшить наше приложение Ratpack с помощью этих полезных функций, разработанных Hystrix.
2. Maven Dependency
Чтобы использовать Hystrix с Ratpack, нам нужна зависимость ratpack-hystrix в проекте pom.xml
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-hystrix</artifactId>
<version>1.4.6</version>
</dependency>
Последнюю версию ratpack-hystrix можно найти https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22ratpack-hystrix%22%20AND%20g%3A%22io.ratpack%22 .[Вот].
В состав ratpack-hystrix входит ratpack-core и hystrix-core .
Чтобы использовать реактивные возможности Ratpack, нам также понадобится ratpack-rx:
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-rx</artifactId>
<version>1.4.6</version>
</dependency>
Последняя версия ratpack-rx может быть найдена Вот .
3. Обслуживание с помощью команды Hystrix
При использовании Hystrix базовые службы обычно заключаются в HystrixCommand или HystrixObservableCommand .
Hystrix поддерживает выполнение этих команд синхронными, асинхронными и реактивными способами. Среди них только реактивный является неблокирующим и официально рекомендованным.
-
В следующих примерах мы создадим некоторые конечные точки, которые извлекают профиль из Github REST API . **
3.1. Реактивное выполнение команд
Во-первых, давайте создадим реактивный бэкэнд-сервис с Hystrix:
public class HystrixReactiveHttpCommand extends HystrixObservableCommand<String> {
//...
@Override
protected Observable<String> 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<String> resumeWithFallback() {
return Observable.just("eugenp's reactive fallback profile");
}
}
Здесь реактивный Ratpack HttpClient используется для выполнения запроса GET. HystrixReactiveHttpCommand может работать как реактивный обработчик:
chain.get("rx", ctx ->
new HystrixReactiveHttpCommand(
ctx.get(HttpClient.class), eugenGithubProfileUri, timeout)
.toObservable()
.subscribe(ctx::render));
Конечная точка может быть проверена с помощью следующего теста:
@Test
public void whenFetchReactive__thenGotEugenProfile() {
assertThat(appUnderTest.getHttpClient().getText("rx"),
containsString("www.baeldung.com"));
}
3.2. Асинхронное выполнение команд
Асинхронное выполнение HystrixCommand ставит команду в очередь в пуле потоков и возвращает Future :
chain.get("async", ctx -> ctx.render(
new HystrixAsyncHttpCommand(eugenGithubProfileUri, timeout)
.queue()
.get()));
HystrixAsyncHttpCommand выглядит так:
public class HystrixAsyncHttpCommand extends HystrixCommand<String> {
//...
@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";
}
}
Здесь мы используем блокирующий HttpClient вместо неблокирующего, потому что мы хотим, чтобы Hystrix управлял время ожидания фактической команды, поэтому нам не нужно обрабатывать ее самостоятельно при получении ответа от Future . Это также позволяет Hystrix выполнять откат или кэшировать наш запрос.
Асинхронное выполнение также дает ожидаемый результат:
@Test
public void whenFetchAsync__thenGotEugenProfile() {
assertThat(appUnderTest.getHttpClient().getText("async"),
containsString("www.baeldung.com"));
}
3.3. Синхронное выполнение команд
Синхронное выполнение выполняет команду непосредственно в текущем потоке:
chain.get("sync", ctx -> ctx.render(
new HystrixSyncHttpCommand(eugenGithubProfileUri, timeout).execute()));
Реализация HystrixSyncHttpCommand практически идентична HystrixAsyncHttpCommand за исключением того, что мы даем ему другой запасной результат. Когда он не отступает, он ведет себя так же, как реактивное и асинхронное выполнение:
@Test
public void whenFetchSync__thenGotEugenProfile() {
assertThat(appUnderTest.getHttpClient().getText("sync"),
containsString("www.baeldung.com"));
}
4. Метрики
Регистрируя ссылку:/ratpack-google-guice[Guice module]- HystrixModule в реестр Ratpack, мы можем направить запрос в объеме метрики и предоставляют потоки событий через конечную точку GET :
serverSpec.registry(
Guice.registry(spec -> spec.module(new HystrixModule().sse())))
.handlers(c -> c.get("hystrix", new HystrixMetricsEventStreamHandler()));
Https://ratpack.io/manual/current/api/ratpack/hystrix/HystrixMetricsEventStreamHandler.html[HystrixMetricsEventStreamHandler] помогает передавать метрики Hystrix в формате text/event-stream , так что мы можем отслеживать метрики в Hystrix Dashboard .
Мы можем настроить standalone панель инструментов Hystrix и добавить наш поток событий Hystrix в список мониторов, чтобы увидеть, как работает наше приложение Ratpack:
ссылка:/uploads/Snip20170815__1.png%20775w[]
После нескольких запросов к нашему приложению Ratpack мы можем увидеть связанные с Hystrix команды на панели инструментов.
4.1. Под капотом
В HystrixModule Hystrix Concurrency Strategy регистрируется в Hystrix через HystrixPlugin для управления контекстом запроса с помощью реестра Ratpack. Это устраняет необходимость инициализации контекста запроса Hystrix перед началом каждого запроса.
public class HystrixModule extends ConfigurableModule<HystrixModule.Config> {
//...
@Override
protected void configure() {
try {
HystrixPlugins.getInstance().registerConcurrencyStrategy(
new HystrixRegistryBackedConcurrencyStrategy());
} catch (IllegalStateException e) {
//...
}
}
//...
}
5. Заключение
В этой быстрой статье мы показали, как Hystrix можно интегрировать в Ratpack и как перенести метрики нашего приложения Ratpack в Hystrix Dashboard для лучшего обзора производительности приложения.
Как всегда, полную реализацию можно найти по адресу the проект Github .