服务与服务之间有业务关联就需要调用,当被调用的服务发生故障(上线后多半是由于网路原因导致连接超时),必然会波及到服务调用者。通俗讲,断路器就是在低层级的服务发生故障时将服务间的连接断开。
个人学习总结:
链接:【springboot、springcloud、docker 等,学习目录】
A、B、C、D四个服务依赖关系:A~>B~>C~>D,当D服务发生故障,若此时C、D之间的连接没有断开,那么D服务会将故障传递给C服务,导致C服务也不可以访问,随着时间的推移,B、A服务都会发生故障,在复杂的系统中甚至会波及到整个系统。
图片、翻译均来自官网。
Netiflix 公司创建了一个已实现断路器模式名为Hystrix 的内库,在微服务架构中通常会有多层级的嵌套调用,低层级服务的失败可能串联导致到用户层次的失败。当断路器断开或者错误时,上图中的Fallback 可以由开发人员指定。题外话:Hystrix :豪猪,浑身长满刺可以保护自己,所以用作断路器的名称。
分为 常规模式 和 Feign整合的模式,一般模式本节在Ribbon中实现,一般模式也可以在Feign中使用。
(注意:本节内容中使用用户微服务(A) 调用 文章微服务(B)。)
常规模式:
1、新建springcloud_user_ribbon_hystrix模块
复制user_ribbon模块,改名、父子pom依赖、导入工程、修改spring.application.name启动类。
2、官网基本使用
Ribbon 中使用 Hystrix,导入依赖、添加注解、指定回退方法。
3、springcloud_user_ribbon_hystrix中添加pom依赖:
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
4、修改 RibbonController:
@Slf4j
@RestController
@RequestMapping(value = "/ribbon")
public class RibbonController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
// Hystrix 断路器
@HystrixCommand(fallbackMethod = "getArticleFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") // 超时时间默认一秒
})
//@HystrixCommand(fallbackMethod = "getArticleFallback")
@GetMapping("article/{id}")
public ApiResult getArticle(@PathVariable("id") String id) {
ApiResult apiResult = this.restTemplate.getForObject("http://springcloud-article/article/" + id, ApiResult.class);
return apiResult;
}
/**
* Hystrix 回退方法
* 参数和返回值要和作用的方法一致 方法名称自定义
*/
public ApiResult getArticleFallback(String id) {
//return /* something useful */;
return ApiResult.ok(id);
}
}
配置属性:
如上RibbonController中使用commandProperties 配置超时时间。
5、测试:
5.1、启动Eureka、springcloud_user_ribbon_hystrix,文章微服务。
5.2、请求:http://127.0.0.1:8081/ribbon/article/1
5.2.1、文章微服务不打断点,可正常访问。
5.2.2、打上断点,5秒(设置的超时时间)后返回:
1、新建springcloud_user_feign_hystrix模块:
复制user_feign模块,改名、父子pom、导入工程、修改spring.application.name、启动类。
2、官网介绍:
如果你的classpath下已经有了Hystrix,并且 feign.hystrix.enable=true ,feign 将会使用断路器包装所有的方法。禁用一个feignclient 只需要添加如上配置。
3、feign中已经包含了Hystrix,不需要引依赖。
4、修改application.yml:
# 开启feign 的断路器
feign:
hystrix:
enabled: true
5、修改FeignArticleClient:
@FeignClient(name = "springcloud-article", fallback = FeignArticleClientFallback.class )
public interface FeignArticleClient {
/**
* 根据id查询文章信息
* @PathVariable(value = "id") 必须指定value参数,不然报错
*/
@RequestMapping(value = "/article/{id}",method = RequestMethod.GET)
public ApiResult getInfo(@PathVariable(value = "id") String id);
}
6、新建FeignArticleClientFallback,实现FeignArticleClient接口:
/**
* @Auther: xf
* @Date: 2018/12/24 23:30
* @Description: Feignclient 断路器回退
*/
@Component
public class FeignArticleClientFallback implements FeignArticleClient {
@Override
public ApiResult getInfo(@PathVariable(value = "id") String id) {
return ApiResult.ok("hystrix 熔断");
}
}
注意:@Component注解、实现自己的FeignClient接口。
7、测试:
7.1、启动Eureka、springcloud_user_feign_hystrix,文章微服务。
7.2、请求接口:http://127.0.0.1:8081/feign/findArticleById/5
7.2.1、文章微服务不打断点,可正常访问。
7.2.2、打上断点返回:
8、若需要返回熔断的异常信息:
如果你需要得到fallback被触发的原因,那么需要在@FeignClient
中使用fallbackFactory
属性。
8.1、新建FallbackFactory:
/**
* @Auther: xf
* @Date: 2018/12/24 23:45
* @Description: Feignclient 断路器回退 factory 获取异常信息
*/
@Slf4j
@Component
public class FeignArticleClientFallbackFactory implements FallbackFactory {
@Override
public FeignArticleClient create(Throwable throwable) {
return new FeignArticleClient() {
@Override
public ApiResult getInfo(String id) {
// return new Hello("fallback; reason was: " + cause.getMessage());
log.info(">throwable, {}", throwable.getMessage());
return ApiResult.ok("fallback; reason was: " + throwable.toString() + " : "+ throwable.getMessage());
}
};
}
}
8.2、修改Feignclient 使用FallbackFactory属性:
@FeignClient(name = "springcloud-article", fallbackFactory = FeignArticleClientFallbackFactory.class )
//@FeignClient(name = "springcloud-article", fallback = FeignArticleClientFallback.class )
public interface FeignArticleClient {
/**
* 根据id查询文章信息
* @PathVariable(value = "id") 必须指定value参数,不然报错
*/
@RequestMapping(value = "/article/{id}",method = RequestMethod.GET)
public ApiResult getInfo(@PathVariable(value = "id") String id);
}
8.3、测试:
8.3.1、修改文章微服务,知道"/0" 异常:
@GetMapping("/{id}")
public ApiResult getInfo(@PathVariable(value = "id") String id){
Article article = articleService.getInfo(id);
log.info(">>>>文章微服务>>>被调用>>>");
int i = 1/0;
return ApiResult.ok(article);
}
8.3.2、启动Eureka、当前服务、文章微服务。
8.3.3、请求:http://127.0.0.1:8081/feign/findArticleById/5
控制台同样会打印出异常信息的日志,得出:fallback 回退信息中包含了异常信息。
至此,常规模式和Feign整合Hystrix模式都已实现。
代码地址:
https://gitee.com/cpla026/springcloud/tree/master/springcloud_parent/springcloud_user_ribbon_hystrix
https://gitee.com/cpla026/springcloud/tree/master/springcloud_parent/springcloud_user_feign_hystrix
个人学习分享
更多 springboot、springcloud、docker 文章,关注微信公众号吧: