Проект 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
|
@RestControllerpublic 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=10000hystrix.command.HelloWorldCommand.execution.isolation.strategy=THREADhystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds=1000hystrix.command.HelloWorldCommand.circuitBreaker.errorThresholdPercentage=50hystrix.command.HelloWorldCommand.circuitBreaker.requestVolumeThreshold=20hystrix.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;@Servicepublic 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», которое я настроил, используя аннотацию для другого имени.
- Если вы заинтересованы в дальнейшем изучении этого примера, вот мой проект на github .
| Ссылка: | Поддержка Spring Cloud для Hystrix от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry. |