全局捕获异常能用 为啥要用降级
坑:
fallback method wasn’t found
目标方法和回退方法参数和返回类型要一致
@HystrixCommand(fallbackMethod = “fallbackHi”)
public String getHi(String x) {
String msg = restTemplate.getForObject(“http://jack/hi“, String.class);
return msg;
}
public String fallbackHi(String x){
return “can’t say hi, and get: ” + x;
}
“`
//如果需要服务降级,那么会调用哪个方法
/**
* 设置自身调用超时时间的峰值,峰值内可以正常运行, 超过了需要有兜底的方法处理,做服务降级fallback
* @param id
* @return
*/
@HystrixCommand(fallbackMethod = "sleep_TimeOutHandler",
commandProperties={
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")
})
public String sleep(String id){
try {
Thread.sleep(3000);
}catch (Exception e){
log.info("睡眠异常");
}
return "调用sleep成功----端口号:"+SERVER_PORT+"id为: "+id;
}
public String sleep_TimeOutHandler(String id){
return "线程池:"+Thread.currentThread().getName()+"o(╥﹏╥)o";
}
}
在主启动类开启降级
@EnableCircuitBreaker 或者@EnableHystrix
实现服务降级有两种方式:
第一种就是实现HystrixCommand接口,并且重写里面的run 和 服务降级时需要调用的 getFallback()
public class QueryOrderIdCommand extends HystrixCommand<Integer> {
private final static Logger logger = LoggerFactory.getLogger(QueryOrderIdCommand.class);
private OrderServiceProvider orderServiceProvider;
public QueryOrderIdCommand(OrderServiceProvider orderServiceProvider) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("orderService"))
.andCommandKey(HystrixCommandKey.Factory.asKey("queryByOrderId"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withCircuitBreakerRequestVolumeThreshold(10)//至少有10个请求,熔断器才进行错误率的计算
.withCircuitBreakerSleepWindowInMilliseconds(5000)//熔断器中断请求5秒后会进入半打开状态,放部分流量过去重试
.withCircuitBreakerErrorThresholdPercentage(50)//错误率达到50开启熔断保护
.withExecutionTimeoutEnabled(true))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties
.Setter().withCoreSize(10)));
this.orderServiceProvider = orderServiceProvider;
}
@Override
protected Integer run() {
return orderServiceProvider.queryByOrderId();
}
@Override
protected Integer getFallback() {
return -1;
}
}
- execute()实际是调用了queue().get()
- queue()实际调用了toObservable().toBlocking().toFuture()
触发服务降级的条件:
延时,默认的访问延时为1s 解决方案: 服务延时
程序bug运行时异常 解决方案: 服务降级
服务宕机(把服务提供者关掉,服务消费者自己兜底) 解决方案: 服务降级
服务熔断触发服务降级
public String sleep(String id){
// try {
//// Thread.sleep(3000);
//// }catch (Exception e){
//// log.info("睡眠异常");
//// }
int b=4/0;
return "调用sleep成功----端口号:"+SERVER_PORT+"id为: "+id;
}
一般服务降级都放在消费者,提供者也需要有自己的保护机制
如果所有的服务降级都这样写,那么出现的问题就是: 代码量太大了
解决办法一:
在一个类上加@DefaultProperties全局服务降级
注意:服务降级的类上面要加 @HystrixCommand 来表明他需要服务降级方法。
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author zzyy
* @create 2020/3/6 23:20
**/
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_OK(id);
}
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
/*@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})*/
@HystrixCommand
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
//int age = 10/0;
return paymentHystrixService.paymentInfo_TimeOut(id);
}
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
return "我是消费者80,对方支付系统繁忙请10秒种后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
}
/**
* 全局fallback
*
* @return
*/
public String payment_Global_FallbackMethod() {
return "Global异常处理信息,请稍后重试.o(╥﹏╥)o";
}
}
解决办法二:
实现Feign的服务调用接口,重写里面的方法
然后在接口处声明兜底类
@Component
@FeignClient(value = "cloud-provider-hystrix-payment",fallback = GetPaymentFallback.class)
public interface GetPaymentService {
@GetMapping("/getSleet")
public String sleet(@RequestParam("id") String id);
@GetMapping("/getSuccess")
public String succ(@RequestParam("id") String id);