服务熔断与服务降级

熔断与降级的概念都属于服务内调用,正常的外部请求从网关进来时无法使用。

熔断的概念比较好理解,参考电路保险丝,电路中当电流超过规定值一段时间后,其产生的热量会是熔体融化以达到断路的目的。同样的在微服务中当某一服务节点因为突然暴增的请求导致请求堵塞,服务无法在预期时间内返回甚至根本无法返回,此时将服务做熔断,接口请求发送进来时首先判断熔断标志,发现为已熔断的服务后,迅速做出默认响应,而不再做出业务逻辑处理。
在这里插入图片描述
服务降级概念:当服务发生熔断时,由于被调用方响应能力基本丧失,服务以不返回或返回简单结构(一般为自定义异常信息)的方式返回接口请求。

服务熔断与服务降级理解

服务熔断不同于服务宕机,熔断时的服务还是具备响应能力的,只是由于某些问题导致响应过慢或暂时无法响应,服务宕机是由注册中心的心跳监控控制的,心跳检测不活跃的节点会被剔除服务列表,理解的时候注意这一点。

服务降级可以在调用方和被调用方两方进行设置。
设置在调用方时,降级服务直接返回一个"我被熔断了,我不处理了"的标识
在这里插入图片描述
调用方收到这个通知之后会转而调用自己本地的一个方法,设置方式后面会说。

设置在被调用方时,接到请求转向被调用方自己的方法,执行后返回,由于已发生熔断一般为服务某项资源紧缺,所以降级接口一般不进行业务处理,返回默认空结构或错误信息。

springcloud常用服务调用方式

一、restTemplate+ribbon+Hystrix

目前springcloud系列教程多的数不清,这里简单介绍一下,想探究更深的可以百度一下。
在这里插入图片描述
restTemplate:spring提供的http请求发送工具。

ribbon:springcloud全家桶中负责负载均衡的组件,常用注解为@LoadBalanced,也可使用@RibbonClient,不过配置相较@LoadBalanced更为复杂,不过当系统中没有使用服务发现相关组件的话就只能使用@RibbonClient。

Hystrix:中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。Netflix开源的一款容错框架。也就是我们常说的熔断器。
代码示例:

//springboot启动类
public class application{

	@Bean
	//项目启动初始化,为restTemplte增加负载器
	@LoadBalanced
	RestTemplate restTemplate(){
		return new RestTemplate();
	}
	
	public static void main(String[] args) {
		SpringApplication.run(application.class, args);
	}
}

挂一个链接,从源码角度讲解了@LoadBalanced是如何实现负载的
https://blog.csdn.net/xiao_jun_0820/article/details/78917215

这里说下重点,嫌麻烦可以直接看重点
在这里插入图片描述
由于加了@LoadBalanced注解,使用RestTemplateCustomizer对所有标注了@LoadBalanced的RestTemplate Bean添加了一个LoadBalancerInterceptor拦截器。利用RestTempllate的拦截器,spring可以对restTemplate bean进行定制,加入loadbalance拦截器进行ip:port的替换,也就是将请求的地址中的服务逻辑名转为具体的服务地址。

负载过程大体可分成四步:
1、根据serverId获取对应的loadBalancer
2、根据loadBalancer获取具体的server(根据具体的负载策略,获取具体的服务实例)
3、创建ribbonServer
4、执行具体请求
负载说完了我们说一下Hystrix,开启Hystrix只需要在启动类增加@EnableHystrix或者@EnableCricuitBreaker两者区别不大,@EnableHystrix继承了@EnableCricuitBreaker

//开启熔断器
@EnableHystrix
//springboot启动类
public class application{

	@Bean
	//项目启动初始化,为restTemplte增加负载器
	@LoadBalanced
	RestTemplate restTemplate(){
		return new RestTemplate();
	}
	
	public static void main(String[] args) {
		SpringApplication.run(application.class, args);
	}

开启熔断器后在默认的策略下已经会自动开启熔断机制了,配置方面可以在配置文件中添加统一配置,也可以在某一方法上增加具体配置
在这里插入图片描述
配置文件示例:


# 配置熔断策略:
hystrix:
command:
default:
circuitBreaker:
# 强制打开熔断器,如果该属性设置为true,强制断路器进⼊打开状态,将会拒绝所有的请
求。 默认false关闭的
forceOpen: false
# 触发熔断错误⽐例阈值,默认值50%
errorThresholdPercentage: 50
# 熔断后休眠时⻓,默认值5秒
sleepWindowInMilliseconds: 3000
# 熔断触发最⼩请求次数,默认值是20
requestVolumeThreshold: 2
execution:
isolation:
thread:
# 熔断超时设置,默认为1秒
timeoutInMilliseconds: 2000

方法上增加熔断配置主要使用@HystrixCommand进行,与大多数常见组件相同同样的具有注解形式和继承类形式两种配置方式,这里介绍注解形式。

@HystrixCommand(
            commandProperties ={
                    //请求超时时间
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value ="3000" ),
                    //统计窗口内的定义
                    @HystrixProperty(name =
                            "metrics.rollingStats.timeInMilliseconds",value = "8000"),
                    //最小请求数
                    @HystrixProperty(name =
                            "circuitBreaker.requestVolumeThreshold",value = "2"),
                    //错误的请求比例
                    @HystrixProperty(name =
                            "circuitBreaker.errorThresholdPercentage",value = "50"),
                    //自我修复的活窗口时长
                    @HystrixProperty(name =
                            "circuitBreaker.sleepWindowInMilliseconds",value = "3000")
            }
            ,fallbackMethod ="fallBackFun" //回退方法
            //线程池标识,要标识为唯一
            ,threadPoolKey = "findRibbonResumeOpenStateTimeout"
            //线程池属性
            ,threadPoolProperties = {
                    //核心纯种
                    @HystrixProperty(name = "coreSize",value ="1" ),
            //最大等待队列长度
            @HystrixProperty(name = "maxQueueSize",value ="20" )
    }
)
@PostMapping("/getStr")
public String getStr(){
	return "success";
}
//失败回退
public String fallBackFun(){
	return "fail";
}

以上是各种配置,其中fallbackMethod为被调用接口访问发生问题时的应急接口,value值为应急接口方法名。

fallbackMethod触发条件:
1.任务超过了"withExecutionTimeoutInMilliseconds"定义的超时时间;
2.任务抛出了非HystrixBadRequestException的异常;
3.超过了线程池线程数目;
4.熔断器打开;

二、feignClient

feign是声明式的web service客户端,Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

在微服务启动时,Feign会进行包扫描,对加@FeignClient注解的接口,按照注解的规则,创建远程接口的本地JDK Proxy代理实例。然后,将这些本地Proxy代理实例,注入到Spring IOC容器中。当远程接口的方法被调用,由Proxy代理实例去完成真正的远程访问,并且返回结果。

相比较restTemplate,feign简化了开发过程,不过feign只能调用同一注册中心内的接口,请求外部接口还是要使用restTemplate。

feign开启:

@EnableFeignClients 
//springboot启动类
public class application{

	public static void main(String[] args) {
		SpringApplication.run(application.class, args);
		
	}
//configuration 自定义配置类,fallback 设置方法回退类
@FeignClient(name = "调用服务名", url = "调用服务的全路径,经常用于本地测试", configuration = FeignConfiguration.class,fallback = fallBackClient.class)
public interface myFeignClient {
    @RequestMapping(value = "/getStr", method = RequestMethod.POST)
    String getStr(@RequestParam("str") String queryStr);
    
}

日志配置:

@Configuration
public class FeignConfiguration {
    /**
     * 日志级别
     * NONE:不输出日志。
	 * BASIC:只输出请求方法的 URL 和响应的状态码以   	及接口执行的时间。
     * HEADERS:将 BASIC 信息和请求头信息输出。
     * FULL:输出完整的请求信息。
     * @return
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

fallback的类实现feignclient的接口,接口调用超时,报错或发生熔断时会直接调用fallback类内的方法

@Component
@RequestMapping("fallback/")
public class  fallBackClient implements myFeignClient {

    @Override
    public String getStr(@RequestParam("str") String queryStr) {
        return "fail";
    }
}

feignClient的使用就是使用@Autowired正常注入像调用本地service一样,还是比较简单的。

大体内容就介绍完了,细节方面就需要好好查查资料,看看源码了,人生有梦,各自精彩。在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐