Проект 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», которое я настроил, используя аннотацию для другого имени.
- Если вы заинтересованы в дальнейшем изучении этого примера, вот мой проект на github .
Ссылка: | Поддержка Spring Cloud для Hystrix от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry. |