微服务宕机时,Ribbon无法实现转发请求,因此引入Hystrix.

Hystrix短路器的核心功能:

  1. 降级: 当后台微服务不可用或访问超时时,则转向执行降级代码,或返回错误信息,或返回缓存数据;
  2. 熔断: 默认配置下,后台微服务10秒内收到的请求达到20个,并且有一半的请求(50%)出现请求失败降级的情况,则Hystrix打开断路器(断路器默认关闭closed),表示后台微服务不可用,让所有请求执行降级代码;当断路器打开5秒后转为半开闭状态,该状态表示当有请求到达时,会尝试向后台微服务转发。如果请求成功,则关闭短路器,表示所有的请求都可请求到达后台微服务;若仍请求失败,则短路器仍保持打开状态。

1. 创建SpringBoot项目,添加依赖:

 

2. 添加Hystrix依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

3. 添加自己项目的common工具类依赖:

 

4. application.yml文件中进行相关配置:

 

5.主启动类上加注解 @EnableCircuitBreaker和@EnableDiscoveryClient:

这三个注解可以用@SpringCloudApplication一个代替

 

6. 创建RibbonController类,在该类中编写springMVC的controller方法,此外指定对应的降级方法,并在controller方法上通过注解标明指定的降级方法:

package com.tedu.sp7.controller;
import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import com.tedu.sp01.pojo.Item;import com.tedu.sp01.pojo.Order;import com.tedu.sp01.pojo.User;import com.tedu.web.util.JsonResult;@RestControllerpublic class RibbonController {    @Autowired    private RestTemplate rt;    @GetMapping("/item-service/{orderId}")
    @HystrixCommand(fallbackMethod = "getItemsFB") //指定降级方法的方法名
    public JsonResult<List<Item>> getItems(@PathVariable String orderId) {        return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
    }    @PostMapping("/item-service/decreaseNumber")
    @HystrixCommand(fallbackMethod = "decreaseNumberFB")
    public JsonResult decreaseNumber(@RequestBody List<Item> items) {        return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
    }    /    @GetMapping("/user-service/{userId}")
    @HystrixCommand(fallbackMethod = "getUserFB")
    public JsonResult<User> getUser(@PathVariable Integer userId) {        return rt.getForObject("http://user-service/{1}", JsonResult.class, userId);
    }    @GetMapping("/user-service/{userId}/score") 
    @HystrixCommand(fallbackMethod = "addScoreFB")
    public JsonResult addScore(@PathVariable Integer userId, Integer score) {        return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score);
    }    /    @GetMapping("/order-service/{orderId}")
    @HystrixCommand(fallbackMethod = "getOrderFB")
    public JsonResult<Order> getOrder(@PathVariable String orderId) {        return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId);
    }    @GetMapping("/order-service")
    @HystrixCommand(fallbackMethod = "addOrderFB")
    public JsonResult addOrder() {        return rt.getForObject("http://order-service/", JsonResult.class);
    }    /    //降级方法的参数和返回值,需要和原始方法一致,方法名任意
    public JsonResult<List<Item>> getItemsFB(String orderId) {        return JsonResult.err("获取订单商品列表失败");
    }    public JsonResult decreaseNumberFB(List<Item> items) {        return JsonResult.err("更新商品库存失败");
    }    public JsonResult<User> getUserFB(Integer userId) {        return JsonResult.err("获取用户信息失败");
    }    public JsonResult addScoreFB(Integer userId, Integer score) {        return JsonResult.err("增加用户积分失败");
    }    public JsonResult<Order> getOrderFB(String orderId) {        return JsonResult.err("获取订单失败");
    }    public JsonResult addOrderFB() {        return JsonResult.err("添加订单失败");
    }}

Hystrix常用配置:

  • hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
    请求超时时间,超时后触发失败降级
  • hystrix.command.default.circuitBreaker.requestVolumeThreshold
    10秒内请求数量,默认20,如果没有达到该数量,即使请求全部失败,也不会触发断路器打开
  • hystrix.command.default.circuitBreaker.errorThresholdPercentage
    失败请求百分比,达到该比例则触发断路器打开
  • hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
    断路器打开多长时间后,再次允许尝试访问(半开),仍失败则继续保持打开状态,如成功访问则关闭断路器,默认 5000