Spring Cloud 之服务熔断问题 (四)
九、 服务熔断
1.服务熔断的相关概念
对于服务熔断来说,我们需要知道以下几个知识点:
- 服务的扇出
服务非常的多,服务之间的调用像扇子一样打出来
- 服务的雪崩
当服务D挂了后,服务B也一样会挂,服务A必然会A,此时访问服务A都是不成功的,导致Tomcat线程池的线程消耗殆尽,没有多余的线程访问其他服务,比如服务M,造成服务雪崩
- 服务的熔断
在服务B调用服务D时,在服务B上设置断路器,当服务D挂了,有线程需要访问服务D时断路器开始工作,这样就可以避免服务雪崩,这就叫服务熔断。
- 服务的降级
什么是服务降级?
比如电商大促,会迎来流量洪峰,为了应对流量洪峰,服务器不会被洪峰打垮,所以要保留(保护、保障)核心服务可用。比如登陆、交易、物流这样的核心服务是可用的,但注册、退货、评价等非核心服务暂时不可用,这就是把注册、退货、评价等这些服务降级了。
2.在Ribbon中实现Hystrix熔断器
1)引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2)在启动类上开启Hyxtrix注解
@EnableDiscoveryClient
@SpringBootApplication
@EnableHystrix
public class MyProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyProductServiceApplication.class, args);
}
}
3)对需要进行熔断方法上设置熔断器,指明错误回调方法
@Override
@HystrixCommand(fallbackMethod = "hiError")
public String addUser(User user) {
ResponseEntity<String> entity = restTemplate.postForEntity("http://user-service/addUser", user, String.class);
return entity.getBody();
}
public String hiError(User user){
return "当前你的网络出现了问题,请联系当地电信运营商";
}
3.在Feign中实现Hystrix熔断器
feign默认集成了Hystrix,需要手动打开
1)在配置文件中添加如下配置:
feign:
hystrix:
enabled: true
注意:如果feign配置了拦截器,那么需要增加hystrix的配置:
#如果设置了拦截器,那么对hystrix线程的隔离级别做这个配置 To set thread isolation to SEMAPHORE
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
2) 编写fallback实现类 实现Feign的接口层
重写接口中的方法,这些方法就是错误回调方法,当发生熔断,对应的方法会被调用
package com.qf.my.product.feign.service.api.fallback;
import com.qf.common.entity.User;
import com.qf.my.product.feign.service.api.ProductFeignAPI;
import org.springframework.stereotype.Component;
@Component
public class ProductFeignFallback implements ProductFeignAPI {
@Override
public String userShow() {
return "当前网络有问题,请检查你的网络";
}
@Override
public String addUser(User user) {
return "当前网络有问题,请检查你的网络";
}
@Override
public User getUserByMap(Long id, String name) {
return null;
}
@Override
public String addUserWithHeader(User user) {
return "当前网络有问题,请检查你的网络";
}
}
3)在Feign接口中配置该错误回调类
fallback = ProductFeignFallback.class
package com.qf.my.product.feign.service.api;
import com.qf.common.entity.User;
import com.qf.my.product.feign.service.api.fallback.ProductFeignFallback;
import com.qf.my.product.feign.service.interceptor.FeignInterceptor;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;
@FeignClient(value="USER-SERVICE",configuration = FeignInterceptor.class,fallback = ProductFeignFallback.class)
public interface ProductFeignAPI {
@RequestMapping("/user/show")
public String userShow();
@PostMapping("/addUser")
public String addUser(@RequestBody User user);
@GetMapping("/getUserByMap")
public User getUserByMap(@RequestParam(name = "id") Long id,@RequestParam(name = "name") String name);
@PostMapping("/addUserWithHeader")
public String addUserWithHeader(@RequestBody User user);
}
4.熔断器打开的条件
- 服务宕机
服务提供者挂了,不在线。
- 服务抛异常
当下游服务抛出了异常,上游熔断被触发
- 服务超时
超出了默认的1s的时间。
配置:
#如果设置了拦截器,那么对hystrix线程的隔离级别做这个配置 To set thread isolation to SEMAPHORE
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
thread:
timeoutInMilliseconds: 10000
# 配置熔断器仪表盘
dashboard:
proxy-stream-allow-list: "localhost"
#feign配置hyxstrix超时时间,需要加上ribbon的超时时间配置
ribbon:
ReadTimeout: 10000
ConnectTimeout: 10000
5.熔断器的半开状态
熔断器被触发,即使下游服务恢复,但下游服务被熔断器降级了,也就是说默认5秒内该服务不能正常访问。熔断器的半开状态:五秒后熔断器会放行一个请求到下游,如果正常则熔断器回到关闭状态,如果不正常,则熔断器继续保持打开状态。