目录
-
- 1.Hystrix简介
- 2.入门案例1-RestTemplate上使用熔断器
- 3.入门案例2-Feign上使用熔断器
- 4.Hystrix异常处理
-
- 4.1 注解形式异常处理
- 4.2 Feign调用异常处理
- 5.参考资料
1.Hystrix简介
在分布式系统中,服务间调用关系错综复杂,则可能会存在某个或某些服务出现故障,导致依赖于它们的其它服务出现调用服务不可用而遭成线程阻塞。Hystrix提供的熔断器功能,能阻止分布式系统出现级联故障。Hystrix通过隔离服务访问点阻止联运故障,并提供了故障解决方案,从而提高整个分布式系统弹性
2.入门案例1-RestTemplate上使用熔断器
入门案例使用第二篇文章中RestTemplate和Ribbon实现负载均衡案例中改造,服务基本信息如下,注册中心在些更换为consul
服务名 | 端口 | 用途 |
---|---|---|
eureka-ribbon-client | 8764 | ribbon客户端 |
eureka-client | 8762 | 服务提供者 |
consul | 192.168.1.100:8500 | 注册中心 |
- eureka-ribbon-client工程引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
-
配置
bootstrap.yml
,注册中心配置与上篇文章配置相同,只修改端口及服务名即可,在些不赘述 -
启动类增加
@EnableHystrix
@SpringBootApplication
@EnableHystrix
@EnableDiscoveryClient
public class EurekaRibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonClientApplication.class, args);}@LoadBalanced@Beanpublic RestTemplate restTemplate(){
return new RestTemplate();}
}
- 调用方法增加
@HystrixCommand
@HystrixCommand,其中fallbackMethod表示调用远程服务出现故障时将要执行的异常处理方法
@Service
public class RibbonService {
@Resourceprivate RestTemplate restTemplate;@HystrixCommand(fallbackMethod = "hiError")public String hi(String name){
return restTemplate.getForObject("http://eureka-client/hi?name={1}", String.class, name);}public String hiError(String name){
return "sorroy,request user name:"+name +",has error";}
}
- 访问
http://localhost:8764/hi?name=zhangsan
出现如下结果
hi zhangsan, i am from port:8762
- 关闭eureka-client服务,再次访问
http://localhost:8764/hi
出现如下结果,表示Hystrix启作用
sorroy,request user name:zhangsan ,has error
3.入门案例2-Feign上使用熔断器
- 案例结构
服务名 | 服务端口 | 作用 |
---|---|---|
consul | 8500 | 注册中心 |
eureka-client | 8762 | 服务提供者 |
eureka-feign-client | 8765 | feign客户端 |
- 案例依赖
由于Feign起步依赖中已经引入了hystrix依赖,依赖信息如下,因此Feign中使用Hystrix不需要额外引入依赖
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-hystrix</artifactId>
</dependency>
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-java8</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><optional>true</optional>
</dependency>
- 配置application.yml中开启Hystrix支持
feign:hystrix:enabled: true
-
@FeignClient中配置fallback
定义调用远程服务时处理回退信息类
HiError
,其中HiError
必须实现@FeignClient
修饰接口
@FeignClient(name = "eureka-client",fallback = HiError.class)
public interface EurekaFeignclientService {
@GetMapping("/hi")String sayHello(@RequestParam String name);
}
- 书写回退处理对象
HiError
@Component
public class HiError implements EurekaFeignclientService {
@Overridepublic String sayHello(String name) {
return "sorry,your name:"+name+"has error";}
}
- 启动服务
eureka-client
、eureka-feign-client
,访问http://localhost:8765/feign/hi?name=lisi
,出现如下信息
hi lisi, i am from port:8762
- 关闭
eureka-client
,再次访问http://localhost:8765/feign/hi?name=list
,出现如下信息,表示Hystrix启作用
sorry,your name:list has error
4.Hystrix异常处理
4.1 注解形式异常处理
1.注解形式异常处理,要求fallback与@HystrixCommand在同一个类中
2.方法中使用Threable获取异常
@Service
public class UserService{
@Resourceprivate RestTemplate restTemplate;private static final Logger logger = LoggerFactory.getLogger(UserService1.class);@HystrixCommand(fallbackMethod = "defaultUser")public String getUser(String username) {
return restTemplate.getForObject("http://provider-service/getUser", String.class, username);}public String defaultUser(String username,Throwable throwable) {
logger.error("发生异常:{}", throwable.getMessage());return "the user:" + username + " does not exist in this system";}
}
查看错误日志如下:
4.2 Feign调用异常处理
- 使用FallbackFactory方式处理异常
@FeignClient中属性使用
fallbckFactory
,注意不要使用成fallback
否则报错
1.feign调用设置fallbackfactory
@FeignClient(name = "provider-service", fallbackFactory = UserServiceFallback.class)
public interface UserService {
@GetMapping("/getUser")String getUser(@RequestParam("username") String username);
}
2.书写fallbackFactory实现类UserServiceFallback
@Component
public class UserServiceFallback implements FallbackFactory<UserService> {
private static final Logger logger = LoggerFactory.getLogger(UserServiceFallback.class);@Overridepublic UserService create(Throwable throwable) {
return new UserService() {
@Overridepublic String getUser(String username) {
logger.error("feign调用发生异常:{}", throwable.getMessage());return "the user" + username + " does not exist in this system,please confirm username"+throwable.getMessage();}};}
}
3.异常日志如下
- feign调用异常处理还可以使用ErrorCoder处理
5.参考资料
- 《重新定义Springcloud实战》
- 《Springcloud微服务实战》
- 《深入理解Spring Cloud与微服务构建》