Ribon的服务降级操作
雪崩效应:
如果短信服务炸了后面的所有服务就会起连锁反应造成全部服务挂掉,这就是雪崩效应,那么其实短信服务又不是我们主要业务,这个时候我们可以采用服务降级,服务降级就是暂时的把短信服务停掉能用就返回不能用就返回个错误,但是它也不会影响到我们的主业务,这样就会保障我们主要服务的正常运行
总结下其实就是对于我们的非主线业务我们一般会才去服务降级的方式保证我们的主要业务正常的运行
服务降级或者是容错我们才使用springcloud提供的Hystrix(豪猪)进行操作:
首先我们在member项目上进行测试
输入测试地址:http://localhost:8088/test?bid=1,返回的信息如下图所示:
返回的controller使我们的Ribbon对RestTemplate做的集群请求,如下所示:
我们把book的服务停掉来看下结果:
我们发现我们的book服务访问不到了,但是这样是不成的我们来给用户看,其实是因为book的模块因为压力太大我手动的给停掉了(后续会使用熔断器进行操作)
所以下面我们使用Hyxtrix进行操作,首先我们先导入Hyxtrix的依赖,在member的pom.xml文件中
<!--Hyxtrix的依赖--> |
然后在Member项目启动类添加一个注解:
package com.laosan.member; |
回到我们Controller中要对test这个方法写一个服务降级的方法:
具体的解决如下所示:
/** |
然后我们通过浏览器进行测试:
返回我们对服务降级所要的结果
但是我们还是有个问题,就是Controller中有多个方法需要服务降级,那么我们就要为每一个方法写一个对应的降级方法,这个时候我们就需要写一个通用的全局的服务降级方法
首先我们要在该Controller中添加一个注解
@Controller 定义一个服务降级的方法 /** 对应的服务降级的方法上面的注解也需要改变下,如下所示: /** } |
但是现在还有个问题就是超时的问题,如果请求超出了时间Hystrix也会对我们进行服务的降级,测试如下所示,我们把我们的book服务启动,并在book的Controller的info方法中设置一个时间:
@GetMapping("/info") 启动book服务 |
我们通过浏览器来查看会不会对我们进行一个服务降级的操作呢,在浏览器进行测试,如下所示:
我们发现也发生了服务降级
这样的话是不太好的我们需要对服务降级的时间进行设置,因为他的默认服务降级的时间是1秒,多于1秒立刻服务降级
具体操作如下所示:
我们要在member项目中创建一个配置文件application.yml文件进行配置:
|
最后在浏览器进行测试:
Spring Cloud 容错机试 Hystrix 服务降级 Feign
我们回到book项目进行操作:
首先我们打开bootstrap.yml进行操作:
spring: |
然后我们打开book项目client包下feign的客户端进行操作:
具体的想法是虽然你的服务挂掉的但是通过hystriy返回一个类似的真实数据
我们发现因为我们feign是个接口没办法进行操作,那么我们可以在接口中写一个静态内部类进行实现就好,具体的如下所示:boot服务中 package com.pb.client; import com.pb.dto.MemberDTO; import com.pb.vo.ResultVo; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; @FeignClient(name="member",fallback = MemberClient.MemberClientFallBack.class) public interface MemberClient { //调用member的服务请求为selectMemberByMobile的 @RequestMapping("/selectMemberByMobile") ResultVo<MemberDTO> selectMemberByMobile(@RequestParam("mobile") String mobile); @Component //通过静态内部类来实现自己进行完成操作 static class MemberClientFallBack implements MemberClient{ @Override public ResultVo<MemberDTO> selectMemberByMobile(String mobile) { //启动服务降级并给一个假的数据返回个调用方 ResultVo<MemberDTO> resultVO = new ResultVo<>(); resultVO.setCode(200); resultVO.setMessage("success"); MemberDTO memberDTO = new MemberDTO(); memberDTO.setMid(0L); resultVO.setData(memberDTO); return resultVO; } } } |
@Transactional
@Override
public void takeBookBookrow(String mobile,Long bid, Date takedate, Date returndate) {
Book book=null;
Optional<Book> option = bookRespository.findById(bid);
if (option.isPresent()){
book=option.get();
}else {
throw new BookNotFoundException("图书未找到");
}
//库存是否为0
if (book.getStock()<=0){
throw new BookLessException("库存不足");
}
//开始插入借书的记录 ,有个数据要先处理一下 mid
MemberDTO memberDTO=null;
ResultVo<MemberDTO> result = memberClient.selectMemberByMobile(mobile);
if (result.getCode() == 200){
memberDTO=result.getData();
if (memberDTO.getMid()==0){
throw new RuntimeException("输入错误");
}
}
//借书记录插入
Borrow borrow=new Borrow();
borrow.setBid(bid);
borrow.setMid(memberDTO.getMid()); //*
borrow.setCreatetime(new Date());
borrow.setTakedate(takedate);
borrow.setReturndate(returndate);
//插入下
borrowRepository.save(borrow);
//修改库存
book.setStock(book.getStock()-1);
bookRespository.saveAndFlush(book);
}
好我们先把book的服务停掉,然后启动我们的前台页面index.html
Hystrix断路器:(必须和服务降级联合使用)
改造member项目的Controller里面的内容:
/** */ |
进行对断路器时间的设置:
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000 circuitBreaker: requestVolumeThreshold : 10 #10个请求 sleepWindowInMilliseconds: 10000 #休息10秒 中 errorThresholdPercentage: 60 #错误的请求达到60% |