springcloud中使用Hystrix保护应用

1.Hystrix入门示例

1.1目前存在的问题

当前项目中如果服务提供者的响速度十分缓慢,导致消费者请求一直处于等待状态,资源得不到释放,一旦请求积累过多,资源耗尽,就会导致服务不可用。顺便提一个名词雪崩效应就是这么引起的,比如存在服务ABCD,服务B是服务A的消费者,服务C,D又是服务B的消费者,服务A的不可用,随后引起服务B的不可用,进而导致服务C,D都不可用,这种因服务提供者的不可用导致消费者不可用,并将服务不可用状态放大的过程就是雪崩效应。
那么如何避免雪崩效应的发生呢:

  • 超时机制
    通过网络请求服务时必须设置超时时间。正常请求时,一般会很快获得响应,当服务提供者不可用或者网络不可用时响应时间都会变的很长,这将会导致请求者会一直等待响应,而每个请求都会对应指定的线程或进程,那么这些资源将无法释放,一般请求堆积或并发量高时就会拖坏这个应用,所以设置超时时间很有必要,在规定的时间内,如果没有获得响应,就默认这个请求失败,释放请求占用的资源。
  • 熔断机制
    这个类似于家用断路器,当发生火灾或线路过载等问题时,断路器就会自动断开(跳闸),我们这里的熔断就是也是同样的道理,比如设置请求超时时间是1秒,一连100个请求都没获得响应,那么基本就可以判断这个服务挂了,为了避免资源的浪费,没有必要再去访问这个不可用的服务了,可以采用断路器断开这个服务。
    最后再补充一下监控。

    1.2简单的Hystrix的示例

  • 引入jar
    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>

老规矩,使用某个组件的功能,首先要在pom文件中引入这个文件的jar

  • Main方法中加入断路器的注解@EnableCircuitBreaker
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @SpringBootApplication
    @EnableEurekaClient
    @RibbonClient(name="microservice-provider-user",configuration = BalanceConfiguration.class)
    @EnableCircuitBreaker
    public class MicroserviceConsumerMovieRibbonWithHystixApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }
    public static void main(String[] args) {
    SpringApplication.run(MicroserviceConsumerMovieRibbonWithHystixApplication.class, args);
    }
    }

@EnableCircuitBreaker的作用是声明这个主方法已经引入了断路器的注解,可以使用断路器了。

  • 实际调用方法中加入出现错误之后的处理方法,并用fallbackMethod指向这个方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @RestController
    public class MovieController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/simple/{id}")
    @HystrixCommand(fallbackMethod ="findUserByIdFallBack" )
    public User findUserById(@PathVariable Long id){
    return restTemplate.getForObject("http://microservice-provider-user/simple/"+id, User.class);
    }

    public User findUserByIdFallBack(Long id){
    User user = new User();
    user.setId(1L);
    user.setUsername("出错了");
    return user;
    }
    }

定义一个方法findUserByIdFallBack作为服务提供者不可用时的处理方法,注意这个方法与原调用方法findUserById参数用和返回类型必须一致,并用@HystrixCommand指定提供者不可用时调用此方法作为响应。

  • application.yml中加入超时时间
    1
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000   #设置超时时间为5秒

配置文件中加入Hystrix的超时时间,这里设置的5秒,但并不是必须。

  • 测试
    依次启动注册中心,服务提供者user,服务消费者movie,第一次正常调用获得响应,随后将提供者user的服务停掉,再次调用发现返回的是我们定义的服务出错时的信息。

    2.健康指标(Health Indicator)和指标流(metrics stream)

  • 健康检查 :
    健康检查就是通过访问 http://你的服务ip:你的服务端口/health 来确定服务的可用状态,上面的一开始是可用的(UP),当把提供者停掉之后,再重复的刷新调用者,触发断路器,发现健康检查里面就会提示服务不可用 。
  • Hystrix指标流:
    若想使用Hystrix的指标流需要引入spring-boot-starter-actuator的依赖。
    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

使用Hystrix指标流可以将/hystrix.stream作为管理端点,访问http://你的服务ip:你的服务端口/hystrix.stream 可以查看项目运行的各个指标。说白了hystrix.stream其实就是一个监控,监控每个API的运行状态,但是它的可读性很差,整页整页的代码不便查看,后面将会说Hystrix的仪表盘(Hystrix Dashboard)。

3.Feign对Hystrix的支持

3.1引入Hystrix的jar依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

3.2给Main方法加入@EnableCircuitBreaker

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker
public class MicroserviceConsumerMovieFeignWithHystrixApplication {

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

加入@EnableCircuitBreaker注解表明这个模块对断路器是支持的。

3.3实现自定义Feign的接口并在这个接口里面写服务不可用的处理方式

1
2
3
4
5
6
7
8
9
10
@Component
public class UserFeignFallBack implements UserFeign{
@Override
public User findUserbyId(Long id) {
User user = new User();
user.setId(-1L);
user.setUsername("服务者出错了");
return user;
}
}

UserFeign就是我们自己定义的那个调用服务的接口客户端,UserFeignFallBack是出错时的处理类,里面重写方法,在其内写出错处理代码。注意UserFeignFallBack类要被Spring管理,添加@Component注解,不然报错。

3.4在Feign客户端中指明出错时的处理类

1
2
3
4
5
@FeignClient(name = "microservice-provider-user", fallback = UserFeignFallBack.class)
public interface UserFeign {
@RequestMapping(value = "/simple/{id}",method = RequestMethod.GET)
public User findUserbyId(@PathVariable("id") Long id);
}

上面的UserFeignFallBack类就是实现的这个UserFeign接口,现在在这个接口上面添加fallback时的处理类为UserFeignFallBack.class,现在就已经写完了,可以起服务进行测试。

4.Hystrix Dashboard的使用

上面我们说过当我们使用指标流,即访问http://192.168.0.12:7909/hystrix.stream 可以看到项目的运行指标,但是可读性很差,如果有一种图形化的界面可以直观的反映出项目的运行状况就非常棒了,确实存在这样的一个东西,那就是Hystrix Dashboard。首先我们需要创建一个Dashboard项目。

  • 新建项目microservice-hystrix-dashboard,引入spring-cloud-starter-hystrix-dashboard的jar。

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    </dependency>
  • main方法中加入@EnableHystrixDashboard注解

    1
    2
    3
    4
    5
    6
    7
    8
    @SpringBootApplication
    @EnableHystrixDashboard
    public class MicroserviceHystrixDashboardApplication {

    public static void main(String[] args) {
    SpringApplication.run(MicroserviceHystrixDashboardApplication.class, args);
    }
    }
  • yml配置文件中配置端口号

    1
    2
    server:
    port: 8030

启动项目访问:http://localhost:8030/hystrix 会看到如下界面:
这里写图片描述
在地址栏中输入你要访问的项目的hystrix.stream可以看到如下页面,这里反映的就是项目运行状态。
这里写图片描述

5.Turbin的使用

使用Dashboard可以获取访问实例的状态,但是生产环境中通常是集群部署,监控单一项目意义不大,Turbin可以做一个数据的聚合,达到监控整个集群的目的。

  • 创建microservice-hystrix-turbin项目,并引入spring-cloud-starter-turbine的jar

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-turbine</artifactId>
    <version>1.3.4.RELEASE</version>
    </dependency>
  • main方法中注入EnableTurbine注解

    1
    2
    3
    4
    5
    6
    7
    8
    @SpringBootApplication
    @EnableTurbine
    public class MicroserviceHystrixTurbinApplication {

    public static void main(String[] args) {
    SpringApplication.run(MicroserviceHystrixTurbinApplication.class, args);
    }
    }
  • yml文件中配置要聚合的实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    server:
    port: 8031
    spring:
    application:
    name: microservice-hystrix-turbine
    eureka:
    client:
    serviceUrl:
    defaultZone: http://admin:qwe123@localhost:8761/eureka
    instance:
    prefer-ip-address: true
    turbine:
    aggregator:
    clusterConfig: default
    appConfig: microservice-consumer-movie-ribbon-with-hystrix,microservice-consumer-movie-feign-with-hystrix
    clusterNameExpression: "'default'"

比如我这里要监控的是microservice-consumer-movie-ribbon-with-hystrix和microservice-consumer-movie-feign-with-hystrix项目。
之后分别启动注册中心,消费者,服务者,turbin和dashboard项目,在dashboard项目中访问turbin项目的指标流即可看到聚合项目的运行状况。

刘俊重 wechat
欢迎关注我的微信公众号
坚持原创技术分享