Hystrix实现微服务的容错处理

熔断器的使用场景

实际生产应用中,如果服务的生产者响应很慢,那么服务的消费者就需要很长的等待时间,直到响应或者超时。在高并发的情景下,如果不做任何的处理,可能会导致服务消费者的资源耗尽甚至整个系统崩溃。

雪崩效应

在微服务架构中可能会存在多个微服务之间层级调用的问题,基础服务故障可能会导致级联故障,造成整个系统不可用的情况,这种现象称为雪崩效应。

熔断器

熔断器可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,防止应用程序不断尝试执行可能会失败的操作,使得应用程序继续执行而不用去长时间的等待直至超时。熔断器可以使应用程序能够诊断错误是否已经修正,应用程序会再次尝试调用操作。

Spring Cloud整合Hystrix

我们复制项目micro-service-consumer-ribbon,将名字改为micro-service-consumer-ribbon-hystrix,接下来需要引入hystrix的依赖。pom文件为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<artifactId>micro-service-consumer-ribbon-hystrix</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<parent>
		<groupId>com.fanfan.cloud</groupId>
		<artifactId>micro-service-spring-cloud-study</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</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-hystrix</artifactId>
		</dependency>
	</dependencies>

	<!-- 引入spring cloud的依赖 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Edgware.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<finalName>consumer-ribbon-hystrix</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

然后在启动类上添加注解@EnableCircuitBreaker或者EnableHystrix,从而为项目启用断路器支持。启动类如下图所示:

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class MicroServiceConsumerRibbonHystrixApplication {

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

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

application.yml文件的配置如下:

server:
  port: 7908


eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
spring:
  application:
    name: cunsumer-ribbon-custom-hystrix

其他的都没有任何改动,除了Controller层,MovieController的代码如下:

@RestController
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    /**
     * 若配置了虚拟主机名则这个请求不可用
     * @param id
     * @return
     */
    @GetMapping("/movie/{id}")
    public User findById(@PathVariable Long id) {
        return restTemplate.getForObject("http://provider/simple/" + id, User.class);
    }

    @HystrixCommand(fallbackMethod = "findByIdFallback", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value="5000"),
            @HystrixProperty(name="metrics.rollingStats.timeInMilliseconds", value="1000")
    },threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "1"),
            @HystrixProperty(name = "maxQueueSize", value = "10")
    })
    @GetMapping("/movie/ribbon/{id}")
    public User findByIdUseVirtualHostName(@PathVariable Long id) {
        return restTemplate.getForObject("http://microservice-provider/simple/" + id, User.class);
    }

    @GetMapping("/log-instance")
    public void logUserInstance() {
        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider");
        System.out.println(serviceInstance.getServiceId()+","+serviceInstance.getHost()+","+serviceInstance.getPort());
    }

    /**
     * 要和原方法有相同的参数和返回值
     * @param id
     * @return
     */
    public User findByIdFallback(Long id) {
        User user = new User();
        user.setId(-1L);
        user.setName("默认用户");
        return user;
    }
}

@HystrixCommand的commandProperties配置@HistrixProperty隔离策略,Hystrix的隔离策略两种: 分别是线程隔离和信号量隔离。
THREAD(线程隔离):HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。
SEMAPHORE(信号量隔离):HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受到信号量个数的限制。
Hystrix中默认并且推荐使用线程隔离(THREAD),因为这种方式有一个除网络超时以外的额外保护。

代码中的参数:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 命令执行超时时间,默认1000ms;
hystrix.command.default.metrics.rollingStats.timeInMilliseconds: 设置统计的时间窗口值的毫秒值;
hystrix.threadpool.default.coreSize: 并发执行的最大线程数,默认10
hystrix.threadpool.default.maxQueueSize: BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
为了验证Hystrix的熔断器功能,我们需要修改micro-service-provider-user的Controller层的方法:

 @GetMapping("/simple/{id}")
    public User findById(@PathVariable Long id) {
//         为了测试Feign的fallback方法
        throw new RuntimeException("服务端测试异常!");
    }

接下来我们启动Eureka、micro-service-provider-user和micro-service-consumer-ribbon-hystrix,然后调用http://localhost:7908/movie/ribbon/1,可以看到如下的结果:
在这里插入图片描述
我们访问http://localhost:7908/hystrix.stream查看hystrix的监控数据。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值