Feign 可以支援 Hystrix,以〈gossip 服務(三)發現〉中的成果為例,若想為 gossip 的 MessageService
加上替代的應變方案,可以如下設置:
package cc.openhome.model;
...略
import cc.openhome.hystrix.MessageServiceFallback;
@FeignClient(value = "msgsvi", fallback = MessageServiceFallback.class)
public interface MessageService {
...略
@GetMapping("newestMessages?n={n}")
Resources<Message> newestMessages(@PathVariable("n") int n);
}
Hystrix 會包裹全部的方法,MessageServiceFallback
提供了執行替代方案時各自呼叫的方法,必須實現 MessageService
,並且必須是個可被 Spring 發現的 Bean,例如:
package cc.openhome.hystrix;
...略
@Service
public class MessageServiceFallback implements MessageService {
...略
@Override
public Resources<Message> newestMessages(int n) {
return new Resources<>(Arrays.asList(new Message("gossiper", 0L, "啊嗚!發生問題,自 epoch 之後都沒有八卦!… XD")));
}
}
記得掃描 Bean 時必須包含這個套件:
@SpringBootApplication(
scanBasePackages={
"cc.openhome.controller",
"cc.openhome.model",
"cc.openhome.aspect",
"cc.openhome.hystrix"
}
)
@EnableFeignClients(
basePackages={
"cc.openhome.model"
}
)
@PropertySource("classpath:path.properties")
public class GossipApplication {
預設對 Hystrix 的支援是關閉的,必須使用 feign.hystrix.enabled
來啟用,因此可以在 application.properties 中加入:
feign.hystrix.enabled=true
如果想為個別的方法設置相關屬性,可以改為 application.yml,並以 yml 語法來設置屬性:
spring:
thymeleaf:
cache: false
feign:
hystrix:
enabled: true
hystrix:
command:
"MessageService#newestMessages(int)":
execution:
isolation:
thread:
timeoutInMilliseconds: 2000
相關的屬性可以在〈Hystrix Configuration〉找到,其中會說明哪些名稱要替換掉,例如,hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds
中的 HystrixCommandKey
就是要替換的部份,因為會涉及 dot 符號等問題而使用 yml 來設置。
如果想取消為 @FeignClient
標註的類別中每個方法做包裹的行為,或者是想在 JavaConfig 中自訂相關 Hystrix 屬性,根據 Feign Hystrix Support,可以自訂 Feign.Builder
來達到目的,詳情可查看 feign/hystrix 的說明,一個例子會像是:
@Bean
public Feign.Builder feignHystrixBuilder() {
return HystrixFeign.builder().setterFactory((target, method) -> {
return HystrixCommand.Setter
// 包裹 MessageService 全部方法
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(MessageService.class.getSimpleName()))
// 逾時設置
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1)
);
}
);
}