微服务学习笔记2

二、服务容错

1.基础知识

  • 雪崩效应
    在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问A服务,而A服务需要调用B
    服务,B服务需要调用C服务,由于网络原因或者自身的原因,如果B服务或者C服务不能及时响应,A服
    务将处于阻塞状态,直到B服务C服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,
    导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难
    性的严重后果,这就是服务故障的“雪崩”效应。

  • 雪崩的根本原因来源于服务之间的强依赖,所以我们可以提前评估,做好熔断隔离限流

  • 服务隔离
    顾名思义,它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。
    当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体
    的系统服务。

    解决方案:通过线程池的方式实现服务隔离

  • 熔断降级
    熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压
    力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这
    种牺牲局部,保全整体的措施就叫做熔断。

  • 服务限流
    限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说
    系统的吞吐量是可以被测算的,为了保证系统的稳固运行,一旦达到的需要限制的阈值,就需要限制流
    量并采取少量措施以完成限制流量的目的。比方:推迟解决,拒绝解决,或者者部分拒绝解决等等。

2.Hystrix

简介

Hystrix 是由Netflix开源的一个延迟和容错库

包裹请求:使用 HystrixCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用
了设计模式中的“命令模式”。

rest实现服务熔断(restTemplate)

  • 配置依赖

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  • 开启熔断

    @EnableCircuitBreaker //开启熔断器
    //@SpringBootApplication
    
    @SpringCloudApplication
    public class OrderApplication {
      //创建RestTemplate对象
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    return new RestTemplate();
    }
    public static void main(String[] args) {
    SpringApplication.run(OrderApplication.class, args);
    }
    }
    
  • 配置熔断降级业务逻辑

    @DefaultProperties(defaultProperties=“全局降级方法名称”)

    @HystrixCommand(fallbackMethod=“降级方法名称”)

    @RestController
    @RequestMapping("/order")
    /**
     * @DefaultProperties : 指定此接口中公共的熔断设置
     *      如果过在@DefaultProperties指定了公共的降级方法
     *      在@HystrixCommand不需要单独指定了
     */
    //@DefaultProperties(defaultFallback = "defaultFallBack")
    public class OrderController {
    
    	@Autowired
    	private RestTemplate restTemplate;
    
    
    	/**
    	 * 使用注解配置熔断保护
    	 *     fallbackmethod : 配置熔断之后的降级方法
    	 */
    	@HystrixCommand(fallbackMethod = "orderFallBack")
    	@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    	public Product findById(@PathVariable Long id) {
    		if(id != 1) {
    			throw  new  RuntimeException("服务器异常");
    		}
    		return restTemplate.getForObject("http://service-product/product/1",Product.class);
    	}
    
    
    	/**
    	 * 指定统一的降级方法
    	 *  * 参数 : 没有参数
    	 */
    	public Product defaultFallBack() {
    		Product product = new Product();
    		product.setProductName("触发统一的降级方法");
    		return product;
    	}
    
    	/**
    	 * 降级方法
    	 *  和需要收到保护的方法的返回值一致
    	 *  方法参数一致
    	 */
    	public Product orderFallBack(Long id) {
    		Product product = new Product();
    		product.setProductName("触发降级方法");
    		return product;
    	}
    
    }
    

    注意事项:熔断的降级逻辑方法必须跟正常逻辑方法保证: 相同的参数列表和返回值声明

  • 超时设置

    hystrix:
    	command:
     		default:
      			execution:
       				isolation:
       				 	thread:
         				timeoutInMilliseconds: 2000
    
  • 隔离方式设置

    hystrix:
      command:
        default:
          execution:
            isolation:
              strategy: ExecutionIsolationStrategy.SEMAPHORE #信号量隔离
              strategy: # ExecutionIsolationStrategy.THREAD 线程池隔离
    
  • 熔断隔离参数配置

    hystrix:
      command:
        default:
          execution:
            isolation:
              strategy: ExecutionIsolationStrategy.SEMAPHORE #信号量隔离
              strategy: # ExecutionIsolationStrategy.THREAD 线程池隔离
              thread:
                timeoutInMilliseconds: 3000 #默认的连接超时时间1秒,若1秒没有返回数据,自动的触发降级逻辑
          circuitBreaker:
            requestVolumeThreshold: 5 #触发熔断的最小请求次数,默认20 /10秒
            sleepWindowInMilliseconds: 10000 #熔断多少秒后去尝试请求 默认 5   打开状态的时间
            errorThresholdPercentage: 50 #触发熔断的失败请求最小占比,默认50%
    

Feign 实现服务熔断

  • Fegin中开启hystrix

    Feign中已经内置了hystrix,但是默认是关闭的需要在工程的 application.yml 中开启对hystrix的
    支持

    feign:
      client:
        config:
          service-product:  #需要调用的服务名称
            loggerLevel: FULL
      #开启对hystrix的支持
      hystrix:
        enabled: true
    
  • 配置FeignClient接口的实现类,在接口上配置添加降级方法的实现类名称

    @Component
    public class ProductFeignClientCallBack implements ProductFeignClient {
    
    	/**
    	 * 熔断降级的方法
    	 */
    	public Product findById(Long id) {
    		Product product = new Product();
    		product.setProductName("feign调用触发熔断降级方法");
    		return product;
    	}
    }
    
    /**
     * 声明需要调用的微服务名称
     *  @FeignClient
     *      * name : 服务提供者的名称
     *      * fallback : 配置熔断发生降级方法
     *                  实现类
     *			@FeignClient 注解中以fallback声明降级方法
     */
    @FeignClient(name="service-product",fallback = ProductFeignClientCallBack.class)
    public interface ProductFeignClient {
    
    	/**
    	 * 配置需要调用的微服务接口
    	 */
    	@RequestMapping(value="/product/{id}",method = RequestMethod.GET)
    	public Product findById(@PathVariable("id") Long id);
    }
    

Hystrix DashBoard监控

  • 添加依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
  • 添加EnableHystrixDashboard 注解

    @EnableHystrixDashboard
    public class OrderApplication {
    public static void main(String[] args) {
    SpringApplication.run(OrderApplication.class, args);
    }
    }
    
  • 暴露所有actuator监控的端点

    management:
      endpoints:
        web:
          exposure:
            include: '*'
    
  • 访问 localhost:端口号/hystrix

    输入监控断点展示监控的详细数据http:/localhost:9001/actuator/hystrix.stream

断路器聚合监控Turbine

  • 创建工程 shop_hystrix_turbine 引入相关坐标

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
  • 配置多个微服务的hystrix监控

    server:
    port: 8031
    spring:
    application:
     name: microservice-hystrix-turbine
    eureka:
    client:
     service-url:
      defaultZone: http://localhost:8761/eureka/
    instance:
     prefer-ip-address: true
    turbine:
     # 要监控的微服务列表,多个用,分隔
    appConfig: shop-service-order
    clusterNameExpression: "'default'"
    

    eureka 相关配置 : 指定注册中心地址
    turbine 相关配置:指定需要监控的微服务列表
    turbine会自动的从注册中心中获取需要监控的微服务,并聚合所有微服务中的 /hystrix.stream 数据

  • 配置启动类

    @SpringBootApplication
    @EnableTurbine
    @EnableHystrixDashboard
    public class TurbineServerApplication {
    public static void main(String[] args) {
    SpringApplication.run(TurbineServerApplication.class, args);
    }
    }
    

熔断器的三个状态

熔断器有三个状态 CLOSEDOPENHALF_OPEN 熔断器默认关闭状态,当触发熔断后状态变更为
OPEN ,在等待到指定的时间,Hystrix会放请求检测服务是否开启,这期间熔断器会变为 HALF_OPEN 半
开启状态,熔断探测服务可用则继续变更为 CLOSED 关闭熔断器。

Closed :关闭状态(断路器关闭),所有请求都正常访问。代理类维护了最近调用失败的次数,
如果某次调用失败,则使失败次数加1。如果最近失败次数超过了在给定时间内允许失败的阈值,
则代理类切换到断开(Open)状态。此时代理开启了一个超时时钟,当该时钟超过了该时间,则切
换到半断开(Half-Open)状态。该超时时间的设定是给了系统一次机会来修正导致调用失败的错
误。
Open :打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间
内失败请求百分比达到阈值,则触发熔断,断路器会完全关闭。默认失败比例的阈值是50%,请求
次数最少不低于20次。
Half Open :半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路
器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则
继续保持打开,再次进行5秒休眠计时。

  • 修改熔断策略

    hystrix:
      command:
        default:
          execution:
            isolation:
              strategy: ExecutionIsolationStrategy.SEMAPHORE #信号量隔离
              strategy: # ExecutionIsolationStrategy.THREAD 线程池隔离
              thread:
                timeoutInMilliseconds: 3000 #默认的连接超时时间1秒,若1秒没有返回数据,自动的触发降级逻辑
          circuitBreaker:
            requestVolumeThreshold: 5 #触发熔断的最小请求次数,默认20 /10秒
            sleepWindowInMilliseconds: 10000 #熔断多少秒后去尝试请求 默认 5   打开状态的时间
            errorThresholdPercentage: 50 #触发熔断的失败请求最小占比,默认50%
    

    requestVolumeThreshold :触发熔断的最小请求次数,默认20
    errorThresholdPercentage :触发熔断的失败请求最小占比,默认50%
    sleepWindowInMilliseconds :熔断多少秒后去尝试请求

隔离策略

  • 线程池隔离策略: 使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超
    时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资
    源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处
    理)

  • 信号量隔离策略: 使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判
    断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请
    求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发
    流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服
    务)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TrKfaPYM-1602131821264)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1602074642196.png)]

3.Sentinel

获取 Sentinel 控制台

您可以从官方网站中 下载最新版本的控制台 jar 包,下载地址如下:
https://github.com/alibaba/Sentinel/releases/download/1.6.3/sentinel-dashboard-1.6.3.jar

  • 使用如下命令启动控制台:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -
Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
  • 引入JAR包
    客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。可以通过 pom.xml 引入 JAR 包:
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
  • 配置启动参数

    spring:
    cloud:
     sentinel:
      transport:
       dashboard: localhost:8080
    

    这里的 spring.cloud.sentinel.transport.dashboard 配置控制台的请求路径。

  • 父工程引入 alibaba实现的SpringCloud

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2.1.0.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    

    子工程中引入 sentinel

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    

配置熔断降级方法

@GetMapping("/buy/{id}")
@SentinelResource(value="order",blockHandler = "orderblockHandler",fallback
= "orderfallback")
public Product order(@PathVariable Long id) {
return restTemplate.getForObject("http://shop-service-
product/product/1", Product.class);
}
//降级方法
public Product orderblockHandler(Long id) {
Product product = new Product();
product.setId(-1l);
product.setProductName("触发熔断降级方法");
return product;
}
//降级方法
public Product orderfallback(Long id) {
Product product = new Product();
product.setId(-1l);
product.setProductName("触发抛出异常方法");
return product;
}

在需要被保护的方法上使用 @SentinelResource注解进行熔断配置。与Hystrix不同的是,Sentinel对抛
出异常和熔断降级做了更加细致的区分,通过 blockHandler 指定熔断降级方法,通过 fallback 指定
触发异常执行的降级方法。

Rest实现熔断

/**
	 * sentinel支持对restTemplate的服务调用使用sentinel方法.在构造
	 *  RestTemplate对象的时候,只需要加载@SentinelRestTemplate即可
	 *
	 *  资源名:
	 *       httpmethod:schema://host:port/path :协议、主机、端口和路径
	 *       httpmethod:schema://host:port :协议、主机和端口
	 *
	 *  @SentinelRestTemplate:
	 *    异常降级
	 *      fallback      : 降级方法
	 *      fallbackClass : 降级配置类
	 *    限流熔断
	 *      blockHandler
	 *      blockHandlerClass
	 */

	@LoadBalanced
	@Bean
	@SentinelRestTemplate(fallbackClass = ExceptionUtils.class,fallback = "handleFallback",
		blockHandler = "handleBlock" ,blockHandlerClass = ExceptionUtils.class
	)
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

	

@SentinelRestTemplate 注解的属性支持限流( blockHandler , blockHandlerClass )和降级( fallback , fallbackClass )的处理。
其中 blockHandlerfallback 属性对应的方法必须是对应 blockHandlerClass
fallbackClass 属性中的静态方法。
该方法的参数跟返回值跟org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一
致,其中参数多出了一个 BlockException 参数用于获取 Sentinel 捕获的异常。

public class ExceptionUtils {

	/**
	 * 静态方法
	 *      返回值: SentinelClientHttpResponse
	 *      参数 : request , byte[] , clientRquestExcetion , blockException
	 */
	//限流熔断业务逻辑
	public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
		return new SentinelClientHttpResponse("abc");
	}

	//异常降级业务逻辑
	public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
		ClientHttpRequestExecution execution, BlockException ex) {
		return new SentinelClientHttpResponse("def");
	}

}

Sentinel RestTemplate 限流的资源规则提供两种粒度:
httpmethod:schema://host:port/path :协议、主机、端口和路径
httpmethod:schema://host:port :协议、主机和端口

Feign实现熔断

  • 引入依赖

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • 开启sentinel 支持

    #激活sentinel的支持
    feign:
      sentinel:
        enabled: true
    
  • 配置FeignClient及熔断方法

两种粒度:
httpmethod:schema://host:port/path :协议、主机、端口和路径
httpmethod:schema://host:port :协议、主机和端口

Feign实现熔断

  • 引入依赖

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • 开启sentinel 支持

    #激活sentinel的支持
    feign:
      sentinel:
        enabled: true
    
  • 配置FeignClient及熔断方法

    和使用Hystrix的方式基本一致,需要配置FeignClient接口以及通过 fallback 指定熔断降级方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值