精华内容
下载资源
问答
  • Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。这里大家可能会问:Sentinel 和...

    Sentine

    1.背景

    Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。这里大家可能会问:Sentinel 和之前常用的熔断降级库 Netflix Hystrix 有什么异同呢?Sentinel官网有一个对比和Hystrix迁移到sentinel的文章,这里摘抄一个总结的表格,具体的对比可以点此 链接 查看。 

    功能对比

     从对比的表格可以明显看到,Sentinel比Hystrix在功能性上还要强大一些。

    2.功能

     Sentinel 功能主要体现在三个方面

    2.1 流量控制

        对于系统来说,任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。 

    控制角度如下:

    • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系
    •  运行指标,例如 QPS、线程池、系统负载等
    •  控制的效果,例如直接限流、冷启动、排队等

    2.2 熔断降级

            当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。手段如下

    • 通过并发线程数进行限制 :当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
    • 通过响应时间对资源进行降级:当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。

    2.3 系统负载保护  

              Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果 这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

              针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

    3.使用

    3.1 依赖

        这里我使用sentinel 是基于gradle配置,兼容spring clould alibaba,所以添加如下依赖

    compile'com.alibaba.cloud:spring-cloud-starter-alibaba-sentinel:2.1.0.RELEASE'
    compile group: 'com.alibaba.csp', name: 'sentinel-transport-simple-http', version: '1.6.3'
    

    3.2 注解

          Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException等,当然也支持使用aop的方式,这里演示使用aop的方式,添加如下配置类

    @Configuration
    public class SentinelAspectConfiguration {
        @Bean
        public SentinelResourceAspect sentinelResourceAspect() {
            return new SentinelResourceAspect();
    }
    }

     @SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项 。@SentinelResource 注解包含以下属性

    • value:资源名称,必需项(不能为空)
    • entryType:entry 类型,可选项EntryType.OUT/EntryType.IN(默认为 EntryType.OUT),对应入口控制/出口控制
    • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称。
    • fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理
      • 返回值类型必须与原函数返回值类型一致
      • fllback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。函数签名和fallback一致
    • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

    3.3 示例  

    服务具体实现类

    @Service
    @Slf4j
    public class HelloProviderServiceImpl implements HelloProviderService {
    
      @Autowired
      private ConfigurableEnvironment configurableEnvironment;
    
      // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数
      @Override
      @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {
          ExceptionUtil.class})
      public void test() {
        log.info("Test");
      }
    
      @Override
      @SentinelResource(value = "sayHi", blockHandler = "exceptionHandler", fallback = "helloFallback")
      public String sayHi(long time) {
        if (time < 0) {
          throw new IllegalArgumentException("invalid arg");
        }
        try {
          Thread.sleep(time);
        } catch (InterruptedException e) {
          throw new IllegalArgumentException("inter arg");
        }
        return String.format("Hello time %d", time);
      }
    
    // 这里俗称资源埋点,在设置限流策略的时候会根据此埋点来控制 @Override @SentinelResource(value
    = "helloAnother", defaultFallback = "defaultFallback", exceptionsToIgnore = {IllegalStateException.class}) public String helloAnother(String name) { if (name == null || "bad".equals(name)) { throw new IllegalArgumentException("oops"); } if ("foo".equals(name)) { throw new IllegalStateException("oops"); } return "Hello, " + name; } // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数. public String helloFallback(long s, Throwable ex) { log.error("fallbackHandler:" + s); return "Oops fallbackHandler, error occurred at " + s; } //默认的 fallback 函数名称 public String defaultFallback() { log.info("Go to default fallback"); return "default_fallback"; } // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致. public String exceptionHandler(long s, BlockException ex) { // Do some log here. return "Oops,exceptionHandler, error occurred at " + s; } }

    服务接口

    public interface HelloProviderService {
        public String sayHi(long t) throws InterruptedException;
        String helloAnother(String name);
        void test();
    }
    ExceptionUtil类
    @Slf4j
    public final class ExceptionUtil {
      public static void handleException(BlockException ex) {
         log.info("Oops: " + ex.getClass().getCanonicalName());
      }
    }

    controller 类

    @RestController
    @Slf4j
    public class HelloProviderController {
    
      @Autowired
      HelloProviderServiceImpl helloServiceProviderService;
    
      @GetMapping("/sayHi")
      public String sayHi(@RequestParam(required = false) Long time) throws Exception {
        if (time == null) {
          time = 300L;
        }
        helloServiceProviderService.test();
        
    return helloServiceProviderService.sayHi(time); } @GetMapping("baz/{name}") public String apiBaz(@PathVariable("name") String name) { return helloServiceProviderService.helloAnother(name); } }

    3.4 Sentinel 控制台

    一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。主要可以通过该控制台对服务端设置的资源埋点进行动态的限流配置推送,这样可以灵活的设置限流策略而不用在代码里写死

    • 提供web界面,可视化资源和流量监控、对资源埋点进行配置
    • 具体安装比较简单,所以这里不再提及,可以参考链接 

    3.5 降级策略

    • 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。

    • 异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

    • 异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。

    • 可以启用Sentinel 控制台,在控制台上直接配置熔断降级规则。

      • 打开控制台界面,点击簇点链路,选择程序里的资源埋点,点击降级
      • 配置降级规则www.wityx.com
      • 配置RT模式测试,控制台输入RT和窗口时间
        • url:ip:port/sayHi?time=delayTime, 当 1s 内持续进入 5 个请求 平均delayTime>RT 进入降级服务
      • 配置异常比例,控制台输入异常比例
        • url:ip:port/baz/bad, 当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值设定的异常比例 将在接下来设置的窗口时间内进入降级服务

    Feign

      1. 背景 

        Feign是Netflix公司开源的轻量级的一种负载均衡的HTTP客户端,,使用Feign调用API就像调用本地方法一样,从避免了 调用目标微服务时,需要不断的解析/封装json 数据的繁琐。 Spring Cloud引入Feign并且集成了Ribbon实现客户端负载均衡调用。 通俗一点讲:可以像调用本地方法一样的调用远程服务的方法。
    当然其中也有不少坑等踩。

       2.使用

     Sentinel 适配了 Fegin组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依赖外还需要 2 个步骤:

    • 配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true

    • 加入 openfeign starter 依赖使 sentinel starter 中的自动化配置类生效:
      compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '2.1.3.RELEASE'

    2.1示例

        添加接口 EchoService类,该接口通过@FeignClient(name = "service-provider")注解来绑定该接口对应service01服务

    @FeignClient(name = "nacos-provider-sentianel1", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
    public interface EchoService {
    
      @GetMapping(value = "/sayHi")
      String sayHi(@RequestParam(value = "time", required = false) Long time);
    
      @RequestMapping("/api/{name}")
      String apiBaz(@PathVariable("name") String name);
    }

        其中 @FeignClient 中name 中的值作为 提供服务提供方的名称,该接口中配置当前服务需要调用nacos-provider-sentianel1服务提供的接口。nacos-provider-sentianel1注册到注册服务上,我这里使用的是Nacos.

       服务配置如下

      nacos-provider-sentianel1 中的controller是这个样子的,这里可以看到 和EchoService中的方法签名都是一致的

    @RestController
    public class HelloProviderController2 {
    
      @GetMapping("/echo")
      public String helloConsumer(@RequestParam(required = false) Long time) {
        return "echo";
      }
    
      @GetMapping("/api/{name}") public String apiBaz(@PathVariable("name") String name) { return "another provider " + name; } }

    添加 EchoServiceFallback,这里是fegin的Fallback机制,主要用来做容错处理。因为在网络请求时,可能会出现异常请求,如果还想再异常情况下使系统可用,那么就需要容错处理。

    @Component。
    public class EchoServiceFallback implements EchoService {
    
      @Override
      public String sayHi(Long time) {
        return "sayHi fallback";
      }
    
      @Override
      public String apiBaz(String name) {
        return "apiBaz fallback";
      }
    }

    添加FeignConfiguration 

    @Configuration
    public class FeignConfiguration {
      @Bean
      public EchoServiceFallback echoServiceFallback() {
        return new EchoServiceFallback();
      }
    }

      在上文HelloProviderServiceImpl的基础上添加EchoService调用

    @Service
    @Slf4j
    public class HelloProviderServiceImpl implements HelloProviderService {
    
      @Autowired
      private ConfigurableEnvironment configurableEnvironment;
    
      @Autowired
      EchoService echoService;
    
      // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数
      @Override
      @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {
          ExceptionUtil.class})
      public void test() {
        log.info("Test");
      }
    
      @Override
      @SentinelResource(value = "sayHi", blockHandler = "exceptionHandler", fallback = "helloFallback")
      public String sayHi(long time) {
        if (time < 0) {
          throw new IllegalArgumentException("invalid arg");
        }
        try {
          Thread.sleep(time);
        } catch (InterruptedException e) {
          throw new IllegalArgumentException("inter arg");
        }
        return String.format("Hello time %d", time);
      }
    
      @Override
      @SentinelResource(value = "helloAnother", defaultFallback = "defaultFallback",
          exceptionsToIgnore = {IllegalStateException.class})
      public String helloAnother(String name) {
        if (name == null || "bad".equals(name)) {
          throw new IllegalArgumentException("oops");
        }
        if ("foo".equals(name)) {
          throw new IllegalStateException("oops");
        }
        return "Hello, " + name;
      }
    
      // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
      public String helloFallback(long s, Throwable ex) {
        log.error("fallbackHandler:" + s);
    
        return "Oops fallbackHandler, error occurred at " + s;
      }
    
      //默认的 fallback 函数名称
      public String defaultFallback() {
        log.info("Go to default fallback");
        return echoService.apiBaz("bad");
        //return "default_fallback";
      }
    
      // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
      public String exceptionHandler(long s, BlockException ex) {
        // Do some log here.
        return "Oops,exceptionHandler, error occurred at " + s;
      }
    }

      这里我们在defaultFallback中使用 echoService.apiBaz("bad") 来调用nacos-provider-sentianel1 的apiBaz方法

      在sentinel控制台中配置helloAnother的降级规则,当触发降级后,将会调用acos-provider-sentianel1服务的apiBaz方法,返回结果。

    总结

          使用sentinel控制系统流量,当系统流超出当前服务的接受范围的时候,可以通过Feign 调用降级服务,这样就可构成一个最基础的熔断降级模块,当然Feign中还集成了Ribbon,可以通过配置实现客户端负载均衡调用。

    展开全文
  • 通过编码方式实现熔断降级三. 通过编码了解 Hystrix 熔断降级的执行步骤 一. 简单设置熔断 服务熔断: 设置一个限制,当服务请求超过限制时,拒绝请求,调用服务降级方法给用户提示信息, ,比如最多只能同时访问100个...

    一. 简单设置熔断

    服务熔断: 设置一个限制,当服务请求超过限制时,拒绝请求,调用服务降级方法给用户提示信息, ,比如最多只能同时访问100个请求,超出请求放入缓存队列中,队列已满时,拒绝访问,并且调用链路会有一个自动恢复过程,在恢复期内请求正常了可能还是会走降级方法,要等到关闭熔断

    示例代码: 设置 fusing()方法10秒内是个请求如果与60%发送错误开启熔断执行降级方法 fallBack2().

      // @HystrixProperty 注解中 10, 10000, 60 的解释,10000表示10秒钟内,有10次请求,如果60%报错了,断路器开启
        @GetMapping(value = "/fusing/{id}")
        @HystrixCommand(fallbackMethod ="fallBack2", commandProperties = {
                @HystrixProperty(name="circuitBreaker.enabled", value = "true"), //是否开启断路器
                @HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="20"),//请求次数
                @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="10000"),//时间窗口期
                @HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value = "50")//失败率达到多少跳闸
        })
        public JsonResult fusing(@PathVariable("id") int id){
            System.out.println("开始执行");
            int i = 1/id;
            return JsonResult.successResult("正常执行");
        }
    
    	//降级方法
    	public JsonResult fallBack2(int id){
            System.out.println("降级方法开始执行");
            return JsonResult.successResult("降级方法执行,接收参数为:"+id);
        }
    

    二. 通过编码方式实现熔断降级

    1. 需要设置熔断降级执行的方法
    public class TestService{
    	//假设该方法需要熔断降级处理,该方法返回 JsonResult 类型数据
       public JsonResult myMethod(){
          System.out.println("需要熔断降级的实际方法");
          return JsonResult.successResult("执行成功");
       }
    }
    
    1. 创建继承 HystrixCommand <熔断方法执行返回的数据类型>类的子类,该类中聚合存有熔断执行的方法的类,重写父类 run()方法,在run()方法中调用需要熔断降级的方法,
    import com.common.result.JsonResult;
    import com.netflix.hystrix.*;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class OrderHystrixCommand extends HystrixCommand<JsonResult> {
    
        //1.持有保存了需要设置熔断降级方法的类
        @Autowired
        private TestService testService;
    
        //2.提供带参构造器,创建当前类对象时必须对 TestService 赋值
        public OrderHystrixCommand(TestService testService) {
            //3.在创建该对象时首先执行 setter() 方法,设置线程池,或信号量
            //获取 Setter 赋值给父类,也就是设置熔断机制
            super(setter());
            this.testService = testService;
        }
    
        //4. 配置熔断机制 线程池或信号量方式
    
        //线程池方式原理: 
        //1.在执行需要熔断降级的方法时,首先会针对服务创建一个线程池
        //2.配置线程池的线程个数,线程存活时间,线程列队的个数
        //3.当请求该服务的线程超过,该线程池的规定时执行降级方法
        private static Setter setter() {
            // 服务分组(注意多个服务分组不能重名,一般对应服务)
            HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("order");
            // 服务标识(一般与服务接口对应)
            HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("order");
            // 线程池名称
            HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("order-pool");
    
            // 配置服务熔断规则,配置线程池,超过时执行拒绝策略
            HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter()
                    .withCoreSize(10) //线程池大小为10
                    .withKeepAliveTimeMinutes(15) //线程存活时间15秒
                    .withQueueSizeRejectionThreshold(100); //队列等待的阈值为100
    
            // 命令属性配置Hystrix 开启超时
            HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
                    // 配置服务隔离方式,采用线程池方式实现服务隔离
                    .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                    // 禁止(默认开启超时机制,需要false禁用)
                    .withExecutionTimeoutEnabled(false);
            return HystrixCommand.Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey)
                    .andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties);
    
        }
    
    
        //通过计数器(信号量)方式,设置服务熔断,与上线程池方式保留一个即可,
        //原理:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行
        //当请求进来时先判断计数器的数值,若超过设置的最大线程个数则拒绝该请求
        //若不超过则通行,这时候计数器+1,请求返回成功后计数器-1。
        private static Setter setter2() {
            // 服务分组
            HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("members");
            // 命令属性配置 采用信号量模式(计数器方式)
            HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
                    .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
                    .withExecutionIsolationSemaphoreMaxConcurrentRequests(50); //设置最大进程数,超过则拒绝执行降级方法
            return HystrixCommand.Setter.withGroupKey(groupKey).andCommandPropertiesDefaults(commandProperties);
        }
    
    
        //5.重写父类run()方法,在该方法中调用执行需要熔断降级的方法
        //可以简单理解为将原来调用的需要熔断降级的方法使用run方法再次包裹一次
        //而该方法的实际执行是通过当前类调用父类的 execute()方法
        @Override
        protected JsonResult run() throws Exception {
            JsonResult result = testService.myMethod();
            return result;
        }
    
        //6.重写getFallback()方法,该方法为降级方法,当对服务的请求超过线程池规定 执行拒绝策略,执行该方法
        @Override
        protected JsonResult getFallback() {
            System.out.println("系统错误!");
            return JsonResult.errorResult("熔断方法执行");
        }
    }
    
    1. 通过此处的 myRunTest() 方法接收请求,通过继承了HystrixCommand 的子类 OrderHystrixCommand 调用 execute() 执行 TestService 中需要熔断降级的方法 myMethod()
    	public JsonResult myRunTest() {
    		TestService service = new TestService()
            return new OrderHystrixCommand( service ).execute();
        }
    

    三. 通过编码了解 Hystrix 熔断降级的执行步骤

    1. 首先会创建一个持有需要熔断降级方法的 HystrixCommand 对象

    2. 在创建该对象时,会初始化熔断规则,线程池或信号量,获取到一个代表熔断规则的 Setter

    3. 后续通过 Setter 判断是否需要熔断执行降级方法

    4. HystrixCommand 执行 execute()方法,执行实际的业务接口

    5. 检查是否开启缓存

    6. 检查是否开启了断路器,如果开启,直接执行降级方法

    7. 检查线程池/队列/semaphore是否已经满了,是否不会触发熔断降级机制,如果触发直接执行降级方法

    8. 调用 run() 方法,执行需要熔断降级的方法,返回执行结果

    9. 如果 run() 方法在执行时抛出异常,或返回超时,也会执行降级方法 getFallback()

    10. 线程池方式与信号量方式默认容量是10

    11. 每次调用实际接口成功,超时,失败,拒绝等情况,都会发送给circuit breaker断路器进行统计,后续根据统计结果判断是否需要开启短路等功能

    12. 触发fallback的情况: run()或construct()执行实际接口发生异常,发送超时,或者hystrix线程池中的线程都在运行中,semaphore队列存满时,或者断路器开启时

    hystrix执行实际业务接口的方式
    1. HystrixCommand 对象调用 execute() 方法,同步等待业务接口执行完毕后返回单条结果
    2. 调用 queue() 方法拿到一个Future,属于异步调用,后续通过Future获取单挑=条执行结果
    3. 调用 observe() 订阅一个Observable对象,Obesrvable代表一个接口的返回接口,获取一个接口代表结果的Observable对象的拷贝对象
    4. toObservable()

    线程池方式熔断降级的原理

    1. 在执行需要熔断降级的方法时,首先会针对服务创建一个线程池
    2. 配置线程池的线程个数,线程存活时间,线程列队的个数
    3. 当请求该服务的线程超过,该线程池的规定时执行降级方法
    

    信号量方式降级的原理

    1. 使用一个原子计数器(或信号量)来记录当前有多少个线程在运行
    2. 当请求进来时先判断计数器的数值,若超过设置的最大线程个数则拒绝该请求
    3. 若不超过则通行,这时候计数器+1,请求返回成功后计数器-1。
    

    线程池方式与信号量方式的不同

    1. 线程池方式: tomcat线程接收用户请求后,通过hystrix隔离线程池里的线程执行,从而保证tmcat线程不会因为依赖服务接口的延迟造成其它请求的产生延时等待的问题,当hystrix线程池存满时,直接走fallback
    2. 信号量方式: 通过信号量设置并发数量,信号量方式还是使用的tomcat线程,
    3. 适用场景: 通常涉及到网络请求的有超时问题的大部分使用线程池方式进行隔离,信号量方式一般用在项目内部服务之间相互的访问设置,不涉及网络请求,避免内部的复杂业务代码导致大量的线程延时阻塞问题
    

    断路器执行流程
    断路器默认时间窗口为10秒,运行最大的并发为20个请求,异常比例默认为50%,也就是时间窗口内请求数量达到20个,异常比例大于50%时开启短路功能,在调用接口直接执行fallback降级,经过一段时间后默认5秒,断路器变为half-open半开状态,会尝试让一个请求正常执行,如果执行成功则关闭断路器

    展开全文
  • hystrix是netflix开源的服务熔断组件,在Spring Cloud中整合进来,形成Spring Cloud的熔断降级体系。服务降级主要是为了服务雪崩,造成下游的服务不可用,可用性是分布式服务的必须要求。 1.pom文件修改:(增添...
       hystrix是netflix开源的服务熔断组件,在Spring Cloud中整合进来,形成Spring Cloud的熔断降级体系。服务降级主要是为了服务雪崩,造成下游的服务不可用,可用性是分布式服务的必须要求。
    

    1.pom文件修改:(增添依赖)

    <dependency>
                <groupId>com.netflix.hystrix</groupId>
                <artifactId>hystrix-javanica</artifactId>
                <version>RELEASE</version>
     </dependency>
    

    2.要开启服务,需要在main类上注上@EnableCircuitBreaker

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableCircuitBreaker
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
    }
    

    3.同样,熔断后需要如何处理,需要调用方写处理逻辑。需要在服务方法上加上@HystrixCommand注解

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Arrays;
    
    @RestController
    public class HystrixController {
        @HystrixCommand(fallbackMethod = "fallback")
        @GetMapping("/getProductInfoList")
        public String getProductInfoList(){
            RestTemplate restTemplate=new RestTemplate();
            //调用product服务的listForOrder接口,大家可以根据项目需求自己coding
            return restTemplate.postForObject("http://127.0.0.1:8083/product/listForOrder", Arrays.asList("157875196366160022"),String.class);
        }
        private String fallback(){
            return "太拥挤了,请稍后重试";
        }
    }
    
    

    4.正常访问,效果如图
    在这里插入图片描述
    5.停掉product服务,就会走fallback函数,如图所示:
    在这里插入图片描述
    6.超时设置(可以避免被调用方访问时间较长而调用方访问不到)

    import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Arrays;
    
    @RestController
    @DefaultProperties(defaultFallback = "defaultFallback")
    public class HystrixController {
        @HystrixCommand(commandProperties = {
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
        })
        @GetMapping("/getProductInfoList")
        public String getProductInfoList(){
            RestTemplate restTemplate=new RestTemplate();
            return restTemplate.postForObject("http://127.0.0.1:8083/product/listForOrder", Arrays.asList("157875196366160022"),String.class);
        }
        private String fallback(){
            return "太拥挤了,请稍后重试";
        }
        private String defaultFallback(){
    
            return "默认提示:太拥挤了,请稍后重试";
        }
    }
    
    
    1. Hystrix实现服务熔断
    import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Arrays;
    
    @RestController
    @DefaultProperties(defaultFallback = "defaultFallback")
    public class HystrixController {
        //超时配置
    //    @HystrixCommand(commandProperties = {
    //            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    //    })
        //服务熔断
        @HystrixCommand(commandProperties = {
                @HystrixProperty(name="circuitBreaker.enabled",value = "true"),                 //设置熔断
                @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"),   // 滚动时间窗口中断路器最小请求数
                @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000"),  //休眠时间
                @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "60")   //错误率
        })
        @GetMapping("/getProductInfoList")
        public String getProductInfoList(@RequestParam("number") Integer number){
            if(number%2==0){
                return "success";
            }
            RestTemplate restTemplate=new RestTemplate();
            return restTemplate.postForObject("http://127.0.0.1:8083/product/listForOrder", Arrays.asList("157875196366160022"),String.class);
        }
        private String fallback(){
            return "太拥挤了,请稍后重试";
        }
        private String defaultFallback(){
    
            return "默认提示:太拥挤了,请稍后重试";
        }
    }
    

    8.对熔断可视化的组件Hystrix-dashboard
    8.1pom文件的修改:

    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    

    8.2在启动类上新增@EnableHystrixDashboard注解

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.SpringCloudApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.context.annotation.ComponentScan;
    
    @EnableFeignClients(basePackages = "com.imooc.product.client")
    //@SpringBootApplication
    //@EnableDiscoveryClient
    //@EnableCircuitBreaker
    @SpringCloudApplication
    @ComponentScan(basePackages = "com.imooc")
    @EnableHystrixDashboard //新增可视化组件
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    
    }
    
    

    8.3在application.yml文件新增配置:

    management:
      server:
        servlet:
          context-path: /
      endpoints:
        web:
          exposure:
            include: ["health","info","hystrix.stream"]
    

    8.4启动界面
    在这里插入图片描述
    8.5不停访问后类似如下界面:
    在这里插入图片描述
    小伙伴们有木有学到呢?赶紧动手尝试一波把!

    展开全文
  • Hystrix服务熔断降级

    2021-04-17 14:55:54
    在微服务架构中,每个服务运行在独立的进程中,服务之间通过服务治理来实现服务的发布和订阅,通过远程服务调用的方式消费服务。 如果因为网络原因或者服务自身问题出现调用故障或延迟,则会直接导致调用方对外服务...

    什么是Hystrix

    在微服务架构中,每个服务运行在独立的进程中,服务之间通过服务治理来实现服务的发布和订阅,通过远程服务调用的方式消费服务。
    如果因为网络原因或者服务自身问题出现调用故障或延迟,则会直接导致调用方对外服务也出现延迟,若此时调用方的请求不断积压,就会导致服务的瘫痪。
    为了解决这样的问题,产生了断路器等一系列服务保护机制。断路器是一种开关装置,当线路过载时它能够及时的切断故障线路,避免更严重的后果。
    在微服务中,如果某个服务单元发生故障,则会中断对该服务的调用并执行一个回调函数进行响应,避免长时间的等待而导致服务的瘫痪。
    Spring Cloud Hystrix 实现了断路器、线程隔离等一系列服务保护功能,它也是基于Netflix的Hystrix实现的。

    Hystrix实现服务降级——基于RestTemplate

    Hystrix是作用在服务的消费者上,所以需要在服务的消费端使用。

    1. 添加Hystrix依赖
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
    1. 在启动类添加@EnableCircuitBreaker注解启用断路器
    2. 编写服务调用代码
    package com.wxw.example.springcloudconsumer.controller.hystrix;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class HystrixController {
    
        @Bean
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    
        @Autowired
        private RestTemplate restTemplate;
    
        @RequestMapping("/hystrix/hello")
        @HystrixCommand(fallbackMethod = "fallback")
        public String hystrixTest(){
            String result = restTemplate.getForObject("http://localhost:8080/hello",String.class);
            return result;
        }
    
        
        public String fallback(){
            return "系统繁忙,请稍后!!!";
        }
    
    }
    
    
    1. 如果被调用的服务出现故障则会执行回调fallback实现服务的降级。

    2. 如果一个类中实现降级的内容都一样,则可以在类头部添加@DefaultProperties注解,避免给每个方法都添加相同的注解。

    @DefaultProperties(defaultFallback = "fallback")
    
    1. Hystrix执行降级操作时默认是服务响应时间超过1秒,可以通过配置指定时间
        @HystrixCommand(commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")
        })
    
    其他更多的配置可以通过HystrixCommandProperties类查看
    

    Hystrix实现服务降级——基于OpenFeign

    1. 在配置文件中启用Hystrix
    # 启用Hystrix
    feign.hystrix.enabled=true
    
    1. 创建一个类,实现调用服务的接口,重写接口中的方法,在方法中添加回调的内容,同时在类头部加上@Component注解
    package com.wxw.example.springcloudconsumer.controller;
    
    import com.wxw.example.springcloudconsumer.pojo.User;
    import org.springframework.stereotype.Component;
    
    @Component
    public class HystrixHelloControllerFeign implements IHelloControllerFeign {
    
        @Override
        public String hello() {
            return "调用hello方法触发了Hystrix降级";
        }
    
        @Override
        public String helloUser(User user) {
            return "调用helloUser方法触发了Hystrix降级";
        }
    }
    
    
    1. 在服务调用接口中补充注解,指定刚刚创建的类
    package com.wxw.example.springcloudconsumer.controller;
    
    import com.wxw.example.springcloudconsumer.pojo.User;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @FeignClient(name = "provider-service",fallback = HystrixHelloControllerFeign.class)
    public interface IHelloControllerFeign {
    
        @RequestMapping("/hello")
        String hello();
    
        @RequestMapping(value = "/helloUser")
        String helloUser(@RequestBody User user);
    
    }
    
    

    Hystrix熔断机制

    默认情况下,如果某个服务10秒内,20个请求中出现50%的请求失败,则开启熔断开关。在之后的5秒内,客户端发起的所有请求都不会到服务端,而是直接执行fallback()方法。5秒之后,客户端会尝试发起一个请求到服务端,如果请求正常,则关闭熔断开关恢复正常。
    以上标记的参数都是可以配置的。
    circuitBreaker.requestVolumeThreshold:最小请求次数,默认20个
    circuitBreaker.sleepWindowInMilliseconds:开启熔断开关后系统睡眠时间,默认5秒
    circuitBreaker.errorThresholdPercentage:请求失败数占比,默认50%

    Hystrix隔离机制

    Hystrix提供两种隔离机制,可以通过execution.isolation.strategy参数设置

    1. 线程池隔离(THREAD)
    2. 信号量隔离(SEMAPHORE)
    展开全文
  • 一, 服务稳定性以及熔断降级的意义 需求的多样性, 业务的复杂程度也是不断上升的, 一个接口依赖的服务也会逐步增加, 各个服务的稳定性是需要着重考虑的; 例如一个电商订单场景, 不能因为评论服务异常超时, 而阻止...
  • pigeon熔断降级服务调用在短时间内出现大量的失败且失败率超过一定阀值时,可以通过配置手动或自动触发降级,调用端直接返回默认对象或抛出异常,不会将调用请求发到服务提供方,如果服务提供方恢复可用,客户端...
  • 0, "timeWindow": 10, "minRequestAmount": 100, "statIntervalMs": 1000, "slowRatioThreshold": 0.5 } ] 启动gateway,然后登录sentinel控制台,点击降级规则 可以看到配置降级服务已经存在降级规则。...
  • 2:启动类添加注解开启fegin声明式客户端调用和Hystrix的熔断降级启用策略 package com.itmuch.cloud.microserviceconsumermoviefeign; import org.springframework.boot.SpringApplication; import org....
  • Hystrix入门服务熔断降级 Hystrix就是隔离措施的一种实现,可以设置在某种超时或者失败情形下断开依赖调用或者返回指定逻辑,从而提高分布式系统的稳定性. 比如:订单系统请求库存系统,结果一个请求过去,因为各种...
  • Sentinel熔断降级

    千次阅读 2020-03-12 14:53:10
    分布式系统越来越流行,...下面以客户端基础服务为例,阐述接入公司sentinel熔断实现流量控制、熔断降级为例。客户端基础服务处于公司业务链路中属于中间环节,既要对来自上游开放平台的请求流量控制,又要对下游基...
  • 订单模块问题 1、 订单模块的横向和纵向拆表。 在电商平台中订单表中的数据会越来越多,为了更好的业务...一个接口实现了多个不同数据库表间的查询,在dubbo中可以用group区分。 服务端 服务端中添加group属性,自定义
  • 这篇文章将介绍feign与hystrix结合来实现调用的同时进行熔断降级防止服务雪崩 使用feign的话自然少不了@FeignClient注解,而@FeignClient注解中除了最基本的name等属性之外,如果要整合hystrix一起使用的话,我们...
  • 前几篇文章,咱们基本上已经用Spring Cloud搭建了一个最基本的分布式架构,实现了订单服务通过Feign去调用下游的商品服务,但是,在一个分布式系统里,一个...本篇会继续讲一下Spring Cloud里的服务熔断降级 Hyst...
  • 推荐以下稳定版本号: Spring Boot: 2.1.9.RELEASE Spring Cloud: Greenwich.SR3 一、Hystrix (豪猪) 简介  在微服务架构中,服务服务之间通过远程调用的方式进行...Hystrix 实现了断路器功能,当某个服务发...
  • RPC熔断降级

    千次阅读 2017-02-12 16:20:25
    dubbox等,现在公司内部由于服务之间的依赖关系复杂,故其一服务down了,我们必须保证调用方的服务是可用的,而不必要一直请求调用方,这样只会浪费本服务的资源,影响对外的相应,故引入相应的服务熔断降级。...
  • 前面的文章介绍了配置客户端,实现接口限流。但是在实际应用中,当我们的某个服务接口出现了问题,不能正常...本文介绍通过sentinel实现接口熔断降级。 控制台的启动不再赘述,可以看之前的博客介绍https://blog.cs...
  • 使用Sentinel实现服务熔断降级

    千次阅读 2020-04-18 11:22:38
    使用 Sentinel 实现服务熔断降级 使用 Sentinel 实现限流 , 参见 springcloud-demo , 限流是给服务生产者的保护措施 添加 pom 依赖 <dependency> <groupId>com.alibaba.cloud</groupId> &...
  • 全文概览 [TOC] 为什么需要hystrix hystrix官网地址github Hystrix同样是netfix公司在分布式系统中的贡献。同样的也进入的不维护阶段。不维护不代表被淘汰。只能说明推陈出新技术在不断迭代。...以实现服务不会出
  • 一, Service Provider对外界提供服务,基于QPS模式限流 Service Provider用于对外提供服务, 处理各个消费者的调用请求。为了保护自己作为Provider端的服务不被激增的流量拖垮影响稳定性,可以给 Provider 配置 ...
  • donet 微服务开发 学习-熔断降级目的介绍什么是熔断降级Polly简介Polly简单使用详解Polly异常处理重试处理短路保护Circuit Breaker策略封装超时处理缓存 目的介绍 donet 微服务开发 学习 什么是熔断降级 熔断器如同...
  • Hystrix如何实现熔断降级?代码实现整合RestTemplate 简述 什么是雪崩? 在微服务架构中服务之间会相互调用,如果一个服务不能及时响应,将会导致其他服务阻塞,若此时大量请求涌入将会导致容器的线程资源耗尽,...
  • 上篇文章主要讲了服务治理、高可用安全的服务注册中心,那么本文将对ribbon、hystrix进行介绍,对其如何实现服务负载均衡,以及如何保证服务之间调用资源的隔离、以及发生紧急情况时对服务进行熔断降级操作进行详细...
  • 服务降级:客户端 从整体网站请求负载考虑,当某个服务熔断或者关团之后,服务将不再被调用,此时在客户端,我们可以准备一个FallbackFactory,返回一个默认的值(缺省值),整体的服务水平下降了 但是,好歹能用,比...
  • ####为什么要使用hystrix 在微服务架构中,存在服务之间的相互调用,如果a服务调用b服务,b服务又调用c服务,当此调用链路中出现问题时,但是并发量又很大的时候就容易产生服务雪崩的现象,...服务熔断 服务限流 ...
  • 解决上一个问题,之后我们还问自己一个问题,feign的作用是http的rpc调用,但是http的调用如何优雅的实现服务熔断降级呢?很明显用hystrix,这里又有问题了,hystrix和feign分别生成的动态代理
  • 在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和...Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。 ...
  • 服务熔断服务降级彻底解耦 用@HystrixCommandfallbackMethod的方式不是很好,因为和业务代码耦合度太高,不利于维护,所以需要解耦,就Feign Hystrix整合。 一、springcloud-common项目: 添加FallbackCli...
  • 熔断限流概述 在基于Spring Cloud的微服务架构体系下,按照系统功能边界的不同划分,原先大而全的系统会被拆分为多个不同的微服务,而相应的微服务会提供一组功能关联的服务接口,并向系统中的其他微服务提供服务...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,057
精华内容 422
关键字:

服务熔断降级实现