Статьи

Нежное введение в Hystrix — Hello World

В предыдущем сообщении в блоге я рассказывал о мотивации такой библиотеки, как Netflix Hystrix . Здесь я расскажу о некоторых из самых простых способов начать использовать Hystrix и расскажу о более сложных случаях использования.

Привет, мир

Простой пример Hello World для «Команды Hystrix» следующий:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class HelloWorldCommand extends HystrixCommand<String> {
 
    private static final Logger logger = LoggerFactory.getLogger(HelloWorldCommand.class);
 
    private final String name;
 
    public HelloWorldCommand(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("default"));
        this.name = name;
    }
 
    @Override
    protected String run() throws Exception {
        logger.info("HelloWorld Command Invoked");
        return "Hello " + name;
    }
}

Метод run содержит любое зависимое действие, от которого мы хотим быть защищенным, которое в конечном итоге возвращает параметризованный тип — String в данном конкретном случае. Если вы поклонник библиотеки Netflix Rx-java , то другой способ создания команды Hystrix заключается в следующем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixObservableCommand;
import rx.Observable;
 
public class HelloWorldObservableCommand extends HystrixObservableCommand<String> {
 
    private String name;
 
    public HelloWorldObservableCommand(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("default"));
        this.name = name;
    }
 
    @Override
    protected Observable<String> resumeWithFallback() {
        return Observable.just("Returning a Fallback");
    }
 
    @Override
    protected Observable<String> construct() {
        return Observable.just("Hello " + this.name);
    }
}

Здесь метод «конструкция» возвращает наблюдаемую Rx-Java .

Использование команды Hystrix

Теперь, когда у нас есть команда Hystrix, чтобы обернуть наш вызов, ее можно использовать разными способами, давайте начнем с самого простого синхронного вызова —

1
2
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("World");
assertEquals("Hello World", helloWorldCommand.execute());

Или это можно сделать, чтобы вернуть будущее:

1
2
3
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("World");
Future future = helloWorldCommand.queue();
assertEquals("Hello World", future.get());

Или, что еще лучше, можно сделать так, чтобы возвращалась наблюдаемая Rx-Java:

01
02
03
04
05
06
07
08
09
10
11
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("World");
 
CountDownLatch l = new CountDownLatch(1);
 
Observable<String> obs = helloWorldCommand.observe();
obs.subscribe(
        s -> logger.info("Received : " + s),
        t -> logger.error(t.getMessage(), t),
        () -> l.countDown()
);
l.await(5, TimeUnit.SECONDS);

Наблюдаемый вариант команды также работает в том же духе, однако мы должны противопоставить небольшую разницу в поведении:

1
2
3
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
logger.info("Completed executing HelloWorld Command");
Observable<String> obs = helloWorldCommand.observe();

Есть два способа получить Observable здесь: один такой же, как и выше, с помощью вызова «.observe ()», другой — следующим образом:

1
2
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
Observable<String> obs = helloWorldCommand.toObservable();

другое — использование вызова .toObservable ():

1
2
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
Observable<String> obs = helloWorldCommand.toObservable();

Разница заключается в том, что метод .observe () возвращает Hot Observable, который немедленно начинает выполнение метода «construct», тогда как вариант «.toObservable» возвращает Cold Observable и не будет вызывать метод «construct», если он не подписан на , скажем так:

1
2
3
CountDownLatch l = new CountDownLatch(1);
obs.subscribe(System.out::println, t -> l.countDown(), () -> l.countDown());
l.await();

У меня есть больше информации здесь.

Обратите внимание, что команда Hystrix не является синглтоном, типичный способ использования команды Hystrix — создать ее там, где она требуется, и утилизировать ее после выполнения.

Резервный и командный ключ группы

В конструкторе HelloWorldCommand я вызвал метод конструктора суперкласса со следующей сигнатурой:

1
2
3
4
public HelloWorldCommand(String name) {
    super(HystrixCommandGroupKey.Factory.asKey("default"));
    this.name = name;
}

Этот параметр задает ключ Hystrix «Command group», а также Command Key, который по умолчанию является простым именем класса, он контролирует множество наворотов поведения Hystrix, примером свойств является следующий, и я буду вернемся к специфике этих позже:

01
02
03
04
05
06
07
08
09
10
hystrix.command.HelloWorldCommand.metrics.rollingStats.timeInMilliseconds=10000
hystrix.command.HelloWorldCommand.execution.isolation.strategy=THREAD
hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds=1000
hystrix.command.HelloWorldCommand.execution.isolation.semaphore.maxConcurrentRequests=10
hystrix.command.HelloWorldCommand.circuitBreaker.errorThresholdPercentage=50
hystrix.command.HelloWorldCommand.circuitBreaker.requestVolumeThreshold=20
hystrix.command.HelloWorldCommand.circuitBreaker.sleepWindowInMilliseconds=5000
 
hystrix.threadpool.default.coreSize=10
hystrix.threadpool.default.queueSizeRejectionThreshold=5

Другим поведением, которое мы можем захотеть контролировать, является ответ в случае сбоя вызова зависимого сервиса, резервный метод обеспечивает такое поведение, поэтому рассмотрим случай, когда зависимый сервис всегда терпит неудачу:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class FallbackCommand extends HystrixCommand<String> {
 
    private static final String COMMAND_GROUP="default";
    private static final Logger logger = LoggerFactory.getLogger(FallbackCommand.class);
 
 
    public FallbackCommand() {
        super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
    }
 
    @Override
    protected String run() throws Exception {
        throw new RuntimeException("Always fail");
    }
 
    @Override
    protected String getFallback() {
        logger.info("About to fallback");
        return "Falling back";
    }
}

Здесь зависимый сервисный вызов всегда терпит неудачу, и ответ, как показано в следующем тесте, всегда будет ответом от резервного метода:

1
2
FallbackCommand fallbackCommand = new FallbackCommand();
assertEquals("Falling back", fallbackCommand.execute());

Мониторинг

Прежде чем закончить основы, полезно продемонстрировать потрясающую функцию, которую Hystrix объединяет в терминах потока Hystrix и панели инструментов Hystrix. Давайте начнем с потоков Hystrix, если он обычно включен в качестве сервлета в веб-приложениях на основе Java, он предоставляет поток SSE статистики в реальном времени о поведении команд Hystrix, присутствующих в веб-приложении.

Поскольку моя демонстрация основана на приложении Karyon2 Rx-Netty , мою конфигурацию можно увидеть здесь . Однако информация из потока Hystrix является слишком сырой, и именно здесь встраивается удивительная панель инструментов Hystrix — она ​​потребляет поток Hystrix и показывает агрегированную информацию в реальном времени о том, как выполняет каждая команда Hystrix и различные базовые пулы потоков. У меня есть пример проекта панели инструментов Hystrix, основанный на потрясающем проекте Spring-Cloud . Пример панели инструментов здесь:

HystrixDashboard

Вывод

Это охватывает основы Hystrix, еще многое предстоит сделать, я завершу это в следующем посте с подробным описанием некоторых расширенных функций Hystrix.

Ссылка: Нежное знакомство с Hystrix — Hello World от нашего партнера по JCG Биджу Кунджуммена в блоге all and sundry.