在Spring Cloud (五)、服务容错保护Hystrix(入门)基础之上我们进行演示Hystrix使用详解之请求命令,这里使用的是注解的方式。
-------------------------------------------命令请求------------------------------------------------
一、在spring-boot-hello和ribbon-consume项目中添加User实体类:
package com.example.springboothello.entity;
/**
* @author HDN
* @date 2019/6/19 19:51
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
二、在spring-boot-hello项目中实现/user/{name}接口:HelloController
@RequestMapping(value="user/{name}")
public User user(@PathVariable String name){
return new User(name,20);
}
三、修改ribbon-consume项目(同步执行)
1、在HelloService添加以下内容:
//同步请求
@HystrixCommand
public User getUserByName(String name){
return restTemplate.getForObject("http://HELLO-SERVICE/user/{name}",User.class,name);
}
2、在ConsumerController中添加以下内容:
//同步请求
@RequestMapping(value="/ribbon-consumer-user",method= RequestMethod.GET)
public User userConsumer(){
return helloService.getUserByName("hdn");
}
四、修改ribbon-consume项目(异步执行)
1、在HelloService添加以下内容:
//异步请求
@HystrixCommand
public Future getUserByNameAsync(String name){
return new AsyncResult() {
@Override
public User invoke() {
return restTemplate.getForObject("http://HELLO-SERVICE/user/{name}",User.class,name);
}
};
}
2、 在ConsumerController中添加以下内容:
//异步请求
@RequestMapping(value="/ribbon-consumer-userAsync",method= RequestMethod.GET)
public User userByAsync(){
Future userAsync = helloService.getUserByNameAsync("HDN");
try {
return userAsync.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
五、测试
分别启动eureka-sercer注册中心、hello-service服务提供者和ribbon-consume消费者,然后访问http://localhost:9000/ribbon-consumer-user,出现以下结果:
访问http://localhost:9000/ribbon-consumer-userAsync出现以下结果:
-------------------------------------------服务降级------------------------------------------------
在命令请求的基础上,我们来实验一下服务降级,这里我们用同步请求进行操作:
只需要在getUserByName方法上@HystrixCommand注解中添加fallbackMethod参数来指定具体的服务降级实现方法。
//同步请求
@HystrixCommand(fallbackMethod = "userFallback")
public User getUserByName(String name){
return restTemplate.getForObject("http://HELLO-SERVICE/user/{name}",User.class,name);
}
public User userFallback(String name){
return new User();
}
测试:这是我们断开hello-service服务实例,访问http://localhost:9000/ribbon-consumer-user,会调用userFallback方法,返回:
这里值得注意的是,userFallback方法的参数和返回值要与getUserByName方法的参数和,返回值一样,否则会报错!!!!!
-------------------------------------------异常处理------------------------------------------------
在服务降级的基础上我们进行修改测试:
一、异常传播
在getUserByName方法里添加int =i/0;这是访问http://localhost:9000/ribbon-consumer-user,会抛异常来掉用userFallback方法,返回:
但是,我们想要忽略int=i/0这个异常,我们在使用注册配置Hystrix命令时来制定忽略的异常,只需要通过设置@HystrixCommand注解的ignoreException参数,如下:
//同步请求
@HystrixCommand(ignoreExceptions = {ArithmeticException.class},fallbackMethod = "userFallback")
public User getUserByName(String name){
int i = 1 / 0;
return restTemplate.getForObject("http://HELLO-SERVICE/user/{name}",User.class,name);
}
public User userFallback(String name){
return new User();
}
这时我们再次请求http://localhost:9000/ribbon-consumer-user,它忽略了int=i/0这个异常不会执行userFallback方法,而抛出异常:
二、异常获取
对不同的异常要做针对性的处理,这是就需要我们来获取异常,获取的方式:只需要在fallback实现方法的参数中增加Throwable e对象的定义,这样在方法内部可以通过e.getMessage()来获取出发服务降级的具体异常内容了。
//同步请求
@HystrixCommand(fallbackMethod = "userFallback")
public User getUserByName(String name){
int i = 1 / 0;
return restTemplate.getForObject("http://HELLO-SERVICE/user/{name}",User.class,name);
}
public User userFallback(String name,Throwable e){
logger.info("获取出发服务降级的异常内容:"+e.getMessage());
return new User();
}
访问http://localhost:9000/ribbon-consumer-user因为int i/0会抛出异常而执行userFallback方法,我们可以看到控制台输出的异常内容: