Spring Cloud 容错机试 Hystrix 服务降级 RestTemplate:

Ribon的服务降级操作

雪崩效应:

 如果短信服务炸了后面的所有服务就会起连锁反应造成全部服务挂掉这就是雪崩效应那么其实短信服务又不是我们主要业务这个时候我们可以采用服务降级服务降级就是暂时的把短信服务停掉能用就返回不能用就返回个错误但是它也不会影响到我们的主业务,这样就会保障我们主要服务的正常运行

总结下其实就是对于我们的非主线业务我们一般会才去服务降级的方式保证我们的主要业务正常的运行

服务降级或者是容错我们才使用springcloud提供的Hystrix(豪猪)进行操作:

首先我们在member项目上进行测试

输入测试地址:http://localhost:8088/test?bid=1返回的信息如下图所示

 返回的controller使我们的Ribbon对RestTemplate做的集群请求,如下所示:

 我们把book的服务停掉来看下结果:

我们发现我们的book服务访问不到了但是这样是不成的我们来给用户看其实是因为book的模块因为压力太大我手动的给停掉了(后续会使用熔断器进行操作)

所以下面我们使用Hyxtrix进行操作,首先我们先导入Hyxtrix的依赖,在member的pom.xml文件中

<!--Hyxtrix的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

然后在Member项目启动类添加一个注解:

package com.laosan.member;
@SpringBootApplication
@EnableFeignClients     //开启feign客户端
@EnableCircuitBreaker   //开启断路器
public class MemberApplication {
   public static void main(String[] args) {
      SpringApplication.run(MemberApplication.class, args);
   }
    /**
     * 注入一个RestTemplate
     * @return
     */
   @Bean
    @LoadBalanced   //对RestTemplate对象进行负载均衡操作
   public RestTemplate  getRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }
}

回到我们Controller中要对test这个方法写一个服务降级的方法

具体的解决如下所示:

/**
 * 远程调用我们需要的book服务里面对应的操作
 * @param bid
 * @return
 */
@GetMapping("/test")
@ResponseBody
@HystrixCommand(fallbackMethod = "fallbback")   //服务降级对应的方法
public String test(Long bid) {
    String json = restTemplate.getForObject("http://book/info?bid="+bid, String.class);
    return json;
}

/**
 * 服务降级
 * 该方法的名字随便起
 * 但是该服务降级的方法要求返回值和参数与目标方法保持一致
 * 最后还要在目标方法上添加一个注解
 * @param bid
 * @return
 */
private String fallbback(Long bid) {
    return "当前服系统正忙,请稍后再试。。。";
}

然后我们通过浏览器进行测试

返回我们对服务降级所要的结果

但是我们还是有个问题,就是Controller中有多个方法需要服务降级,那么我们就要为每一个方法写一个对应的降级方法,这个时候我们就需要写一个通用的全局的服务降级方法

首先我们要在该Controller中添加一个注解

@Controller
@CrossOrigin    //跨域问题的解决
@DefaultProperties(defaultFallback = "defaultFallBack")
public class MemberController {
    @Autowired
    private MemberService memberServic

定义一个服务降级的方法

/**
 * 全局的默认的服务降级方法,不需要参数,且返回String或者任何可以被Json序列化的对象
 * @return
 */
private String defaultFallBack() {
     return "【默认服务降级】当前服系统正忙,请稍后再试。。。";
}

对应的服务降级的方法上面的注解也需要改变下,如下所示:

/**
 * 远程调用我们需要的book服务里面对应的操作
 * @param bid
 * @return
 */
@GetMapping("/test")
@ResponseBody
//@HystrixCommand(fallbackMethod = "fallbback")   //服务降级对应的方法
@HystrixCommand     //找的是上面定义的默认的服务降级的方法
public String test(Long bid) {

}

但是现在还有个问题就是超时的问题,如果请求超出了时间Hystrix也会对我们进行服务的降级,测试如下所示,我们把我们的book服务启动,并在book的Controller的info方法中设置一个时间:

@GetMapping("/info")
@ResponseBody
public Map<String, Object> info(Long bid){
    //测试服务降级我们在这里添加了一个2秒的等待时间
    try {
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Map<String, Object> map = new HashMap<String, Object>();
    try {
        Book book = bookService.getInfo(bid);
        map.put("code", "0");
        map.put("message", "success");
        map.put("data", book);
    } catch (Exception e) {
        e.printStackTrace();
        map.put("code", e.getClass().getSimpleName());
        map.put("message", e.getMessage());
    }
    return map;
}

启动book服务

我们通过浏览器来查看会不会对我们进行一个服务降级的操作呢,在浏览器进行测试,如下所示:

 我们发现也发生了服务降级

这样的话是不太好的我们需要对服务降级的时间进行设置,因为他的默认服务降级的时间是1秒,多于1秒立刻服务降级

具体操作如下所示:

我们要在member项目中创建一个配置文件application.yml文件进行配置:


#设置服务降级的最大降级时间
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

最后在浏览器进行测试

Spring Cloud 容错机试 Hystrix 服务降级 Feign

我们回到book项目进行操作:

首先我们打开bootstrap.yml进行操作:

spring:
  application:
    name: book   #这里的名字必须要和Eureka中的服务名称,和配置中心的名字保持一致
  #开启配置中心
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config   #这里的名字要和我Eureka服务中的配置中心名称的服务保持一致
      profile: dev
#注册进服务
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
#在feign中开启hystrix
feign:
  hystrix:
    enabled: true

然后我们打开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里面的内容:

/**
 * 远程调用我们需要的book服务里面对应的操作

*/
@GetMapping("/test")
@ResponseBody
//@HystrixCommand(fallbackMethod = "fallbback")   //服务降级对应的方法
@HystrixCommand
public String test(Long bid) {
        String json = null;
    if(bid % 2 == 0) {
       json = restTemplate.getForObject("http://book/info?bid=" + bid, String.class);
    }
    else {
        json = "success";
    }
    return json;
}

进行对断路器时间的设置:

hystrix:

  command:

    default:

      execution:

        isolation:

          thread:

            timeoutInMilliseconds: 3000

      circuitBreaker:

        requestVolumeThreshold : 10   #10个请求

        sleepWindowInMilliseconds: 10000   #休息10秒 中

        errorThresholdPercentage: 60    #错误的请求达到60%

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值