SpringCloud入门(四):Hystrix服务熔断

在微服务架构中,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。为了解决这个问题,提出了Hystrix服务熔断。 Hystrix断路器,是在当某个服务单元发生故障,向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不会长时间的等待或抛出调用方无法处理的异常,以保证服务调用方线程不会被长时间占用。

Hystrix设计原则:

  1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败。通过第三方客户端访问(通常是通过网络)依赖服务出现失败、拒绝、超时或短路时执行回退逻辑

       2.用快速失败代替排队(每个依赖服务维护一个小的线程池或信号量,当线程池满或信号量满,会立即拒绝服务而不会排队等待)和优雅的服务降级;当依赖服务失效后又恢复正常,快速恢复

       3.提供接近实时的监控和警报,从而能够快速发现故障和修复。监控信息包括请求成功,失败(客户端抛出的异常),超时和线程拒绝。如果访问依赖服务的错误百分比超过阈值,断路器会跳闸,此时服务会在一段时间内停止对特定服务的所有请求

       4.将所有请求外部系统(或请求依赖服务)封装到HystrixCommand或HystrixObservableCommand对象中,然后这些请求在一个独立的线程中执行。使用隔离技术来限制任何一个依赖的失败对系统的影响。每个依赖服务维护一个小的线程池(或信号量),当线程池满或信号量满,会立即拒绝服务而不会排队等待

Hystrix特性

  1.请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.

  2.服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。

  3.依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放

   后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。

  4.请求缓存:比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。

  5.请求合并:我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。

这里主要讲服务熔断和服务降级的实现。

服务熔断:服务提供者异常信息处理

服务熔断是在服务端出现异常或延迟等状况时,回调熔断方法,为客户端返回能处理的响应。主要操作是在服务端也就是在服务提供者。

POM文件:

		<!-- hystrix -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<!-- 将微服务provider侧注册进eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker  //开启熔断
public class CloudProviderHystrix {

    public static void main(String[] args) {
        SpringApplication.run(CloudProviderStarter.class);
    }

}

application.yml:

server:
    port: 8089

spring:
   application:
    name:cloud-provider-hystrix 

eureka:
  client:
    service-url:
      defaultZone: http://eurekaServer7003:7003/eureka/

Controller:

@RestController
public class CloudProviderController { 

    @GetMapping("/provider/get/{message}")
    @HystrixCommand(fallbackMethod = "hystrix")
    public String get(@PathVariable("message") String message){
        throw new RuntimeException("熔断服务,进入服务熔断方法hystrix");
    }

    public String hystrix(@PathVariable("message") String message){
        return "进入服务熔断";
    }    
}

分别启动Eureka注册中心、服务提供端CloudProviderHystrix、服务消费端CloudConsumerFeign。Eureka管理界面:

访问服务消费端:http://localhost:8087/Consumer/get/12345

服务端抛出异常后,会进入自定义的断路器保护方法,返回可以被客户端正常解析的信息。

服务降级:服务消费端

服务降级是指服务消费端在调用服务提供端时,如果服务提供端宕机或出现异常,则服务提供端将调用自己的回调方法,给客户端返回可以解析的正常信息。

服务消费端,POM:

       <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

application.yml:

server:
  port: 8087

feign:
  hystrix: 
    enabled: true    #开启服务降级

eureka:
  client:
    register-with-eureka: false
    service-url: 
      defaultZone: http://eurekaServer7003:7003/eureka/

服务调用接口Service:

//@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX")
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX",fallbackFactory = HystrixFallback.class) //设置回调类
public interface FeignService {

    @RequestMapping(value = "/provider/get/{message}", method = RequestMethod.GET)
    String get(@PathVariable("message") String message);
}

这里@FeignClient注解的fallbackFactory属性指定了回调类HystrixFallback.class,当服务调用出现异常时,会调用该类中的方法。

HystrixFallback类:HystrixFallback implements FallbackFactory<FeignService>

@Component
public class HystrixFallback implements FallbackFactory<FeignService> {
    public FeignService create(Throwable throwable) {
        return new FeignService() {
            public String get(String message) {
                return "服务提供方的服务器异常,进入服务降级";
            }
        };
    }
}

controller:

@RestController
public class CloudFeignController {
    @Autowired
    private FeignService feignService;

    @GetMapping("/Consumer/get/{message}")
    public String getDept(@PathVariable("message") String message){
        return this.feignService.get(message);
    }
}

添加了服务降级的CloudConsumerFeign,需要添加服务回调类,而这个回调类需要实现FallbackFactory<T>接口,重写create方法。application.yml配置文件添加开启服务降级配置:feign.hystrix.enable = true。其他配置和feign的服务调用相同。

服务降级的服务提供者和Eureka注册中心和普通的服务提供者和注册中心配置相同。这里我们在服务提供者的Controller中手动抛出异常:

@RestController
public class CloudProviderController {

    @GetMapping("/provider/get/{message}") 
    public String get(@PathVariable("message") String message){
        throw new RuntimeException("熔断服务,进入服务熔断方法hystrix");
    } 
}

分别启动Eureka注册中心、服务提供者、服务消费者,访问服务者:http://localhost:8087/Consumer/get/12345

小结:

服务熔断是在服务端完成的,针对服务端中某个微服务的方法出现异常时,调用指定的回调方法,返回服务消费者可以解析的信息。而服务降级则是在服务端,针对调用服务的接口,设置回调类,不论是服务端出现异常还是宕机,服务消费者都会返回客户端可以识别的信息。综上可以看出,服务熔断是服务端针对单独微服务方法的处理,而服务降级是服务消费者(客户端)针对服务调用接口的处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值