微服务宕机时,Ribbon无法实现转发请求,因此引入Hystrix.
Hystrix短路器的核心功能:
- 降级: 当后台微服务不可用或访问超时时,则转向执行降级代码,或返回错误信息,或返回缓存数据;
- 熔断: 默认配置下,后台微服务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