Статьи

Поддержка Spring Cloud для Hystrix

Проект Spring Cloud обеспечивает всестороннюю поддержку библиотеки Netflix OSS Hystrix . Ранее я писал о том, как использовать необработанную библиотеку Hystrix для переноса удаленных вызовов. Здесь я расскажу, как можно использовать Hystrix с Spring Cloud.

основы

На самом деле в этом нет ничего особенного, концепции просто переносятся с определенными улучшениями, специфичными для загрузки Spring. Рассмотрим простую команду Hystrix, которая объединяет вызов к удаленной службе:

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
27
28
29
30
31
32
import agg.samples.domain.Message;
import agg.samples.domain.MessageAcknowledgement;
import agg.samples.feign.RemoteServiceClient;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class RemoteMessageClientCommand extends HystrixCommand<MessageAcknowledgement> {
    private static final String COMMAND_GROUP = "demo";
    private static final Logger logger = LoggerFactory.getLogger(RemoteMessageClientCommand.class);
 
    private final RemoteServiceClient remoteServiceClient;
    private final Message message;
 
    public RemoteMessageClientCommand(RemoteServiceClient remoteServiceClient, Message message) {
        super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
        this.remoteServiceClient = remoteServiceClient;
        this.message = message;
    }
 
    @Override
    protected MessageAcknowledgement run() throws Exception {
        logger.info("About to make Remote Call");
        return this.remoteServiceClient.sendMessage(this.message);
    }
 
    @Override
    protected MessageAcknowledgement getFallback() {
        return new MessageAcknowledgement(message.getId(), message.getPayload(), "Fallback message");
    }
}

Здесь нет связанных с Spring классов, и эту команду можно использовать непосредственно в проекте на основе Spring, например, в контроллере следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
@RestController
public class RemoteCallDirectCommandController {
 
    @Autowired
    private RemoteServiceClient remoteServiceClient;
 
    @RequestMapping("/messageDirectCommand")
    public MessageAcknowledgement sendMessage(Message message) {
        RemoteMessageClientCommand remoteCallCommand = new RemoteMessageClientCommand(remoteServiceClient, message);
        return remoteCallCommand.execute();
    }
}

Настройка поведения команды Hystrix обычно выполняется через свойства NetflixOSS Archaius , однако Spring Cloud предоставляет мост для отображения свойств, определенных в Spring, в виде свойств Archaius, это означает, что я могу определить свои свойства, используя специфические для Spring файлы конфигурации, и они будет видно при настройке поведения команды.

Так что, если раньше вы настраивали, скажем, поведение HelloWorldCommand, используя свойства Archaius, которые выглядят так:

1
2
3
4
5
6
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.circuitBreaker.errorThresholdPercentage=50
hystrix.command.HelloWorldCommand.circuitBreaker.requestVolumeThreshold=20
hystrix.command.HelloWorldCommand.circuitBreaker.sleepWindowInMilliseconds=5000

это можно сделать в мире Spring Cloud точно таким же образом в файле application.properties или в файле application.yml следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
hystrix:
  command:
    HelloWorldCommand:
      metrics:
        rollingStats:
          timeInMilliseconds: 10000
      execution:
        isolation:
          strategy: THREAD
          thread:
            timeoutInMilliseconds: 5000
      circuitBreaker:
        errorThresholdPercentage: 50
        requestVolumeThreshold: 20
        sleepWindowInMilliseconds: 5000

Основанный на аннотации подход

Лично я предпочитаю подход, основанный на прямых командах, однако лучше использовать Hystrix в мире Spring, а не аннотации на основе Hystrix -javanica . Использование этой аннотации лучше всего иллюстрируется на примере. Вот удаленный вызов, заключенный в команду Hystrix с аннотациями:

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
27
import agg.samples.domain.Message;
import agg.samples.domain.MessageAcknowledgement;
import agg.samples.feign.RemoteServiceClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
@Service
public class RemoteMessageAnnotationClient  {
 
    private final RemoteServiceClient remoteServiceClient;
 
    @Autowired
    public RemoteMessageAnnotationClient(RemoteServiceClient remoteServiceClient) {
        this.remoteServiceClient = remoteServiceClient;
    }
 
    @HystrixCommand(fallbackMethod = "defaultMessage", commandKey = "RemoteMessageAnnotationClient" )
    public MessageAcknowledgement sendMessage(Message message) {
        return this.remoteServiceClient.sendMessage(message);
    }
 
    public MessageAcknowledgement defaultMessage(Message message) {
        return new MessageAcknowledgement("-1", message.getPayload(), "Fallback Payload");
    }
 
}

Эти аннотации транслируются с использованием аспекта в обычные команды Hystrix за кулисами, однако следует отметить, что использование этого в проекте Spring Cloud не церемонится, оно просто работает. Как и раньше, если поведение необходимо настроить, это можно сделать с помощью специальных свойств команды. Одна небольшая загвоздка в том, что имя команды по умолчанию является именем метода, поэтому в моем примере имя команды было бы «sendMessage», которое я настроил, используя аннотацию для другого имени.

Ссылка: Поддержка Spring Cloud для Hystrix от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry.