在前一步的基础上实现熔断功能
回顾
在Eureka总结中构建了两个服务:用户服务和博客服务,并实现了远端调用。想要实现熔断需要在调用端,即博客服务中做以下修改,贼简单。
0.配置的修改
application.properites中添加
#熔断配置
feign.hystrix.enabled=true
实现方法1
1.创建调用远程服务B的接口UserRemote,并通过fallback属性配置熔断类,注意fallback属性是不带双引号的。
@Service
@FeignClient(name="blog-viewer",fallback = UserRemoteHystrix.class)
public interface UserRemote {
@RequestMapping("/findByUsername")
public String findByUsername(@RequestParam(value="name")String name);
}
2.为UserRemote接口添加实现类,熔断类UserRemoteHystrix.class,实现熔断时执行的代码,这里需要注意的地方是@Component注解,实现UserRemote接口,与远程服务的参数匹配(因为restful请求的参数匹配机制?)
@Component
public class UserRemoteHystrix implements UserRemote {
@Override
public String findByUsername(@RequestParam(value = "name") String name) {
return "熔断啦";
}
}
3.在本地服务的实现类中调用远程接口,方法无需使用注解
public List<Blog> listMyBlogs(String name) {
String userJson = userRemote.findByUsername(name);
//若请求失败则进入熔断类,返回字符串“熔断啦”
if(userJson.equals("熔断啦")){
return null;
}
User user = JSON.parseObject(userJson,new TypeReference<User>(){});
List<Blog> myList = dao.listByAuthorId(user.getId());
return myList;
}
实现方法2
1.A服务远程调用B服务的接口,没有fallback属性,注意服务名和参数名要与服务B一致
@Service
@FeignClient(name="blog-viewer-user")//,fallback = UserRemoteHystrix.class
public interface UserRemote {
@RequestMapping("/findByUsername")
String findByUsername(@RequestParam(value = "name") String name);
}
2.在A服务实现类中添加熔断方法,参数和返回值需要与A服务方法一致,不然会报找不到fallback method错误。并且,声明了熔断方法就无需再声明远程接口的熔断类,我在测试的时候如果熔断类与熔断方法都存在,即使没有使用这个熔断类,也会直接进入声明的熔断方法。我在idea中进入远程调用接口的实现类里发现进到了熔断类中,所以我猜是不是自动注入的时候直接把service的实现类注入了进去,导致远程请求失败,这个问题待查。
/**
* 熔断方法,参数名与返回值名要与listMyBlogs一致
* @param name
* @return
*/
public List<Blog> fail(String name){
System.out.println("我是熔断fallback方法");
return null;
}
3.在A服务实现类中调用远程服务,在方法上使用@HystrixCommand注解,声明fallbackMethod
@Override
@HystrixCommand(fallbackMethod = "fail")
public List<Blog> listMyBlogs(String name) {
String userJson = userRemote.findByUsername(name);
User user = JSON.parseObject(userJson,new TypeReference<User>(){});
List<Blog> myList = dao.listByAuthorId(user.getId());
return myList;
}
Controller
@RestController
public class ListController {
@Autowired
private ContentListService service;
@Autowired
private MyBlogsService myService;//自动注入本地服务,该服务调用了远程服务
@RequestMapping("/myList")
public String myList(String name){
List<Blog> list = myService.listMyBlogs(name);
return JSON.toJSONString(list);
}
}
测试过程
依次开启注册中心,用户服务和博客服务,先发一个myList请求试试,通了之后手动关闭用户服务,再发请求,发现熔断。返回的结果为null