Spring Cloud系列(十一) Hystrix快速入门 (Finchley.RC2版本)

为什么要用断路器?

在微服务架构中,我们将系统拆分成了很多个服务单元,这些单元通过在服务注册中心注册与订阅互相依赖。这就可能造成一个问题,如果出现网络延迟或者依赖的服务出现问题,会直接导致调用方的对外服务也出现延迟,最终会导致调用任务不断积压导致系统崩溃。为了解决这个问题,产生了断路器等一系列的的服务保护机制。

断路器的作用就是在分布式系统中,当某个服务单元出现故障时,通过断路器的故障监控向服务的调用方返回一个错误响应,而不是长时间的等待(类似电路发生短路,通过断路器熔断保险丝来保障安全)。这样就不会使得线程因为调用故障服务长时间得不到释放,最终蔓延到整个系统导致系统崩溃。Spring Cloud Hystrix是基于Netflix的Hystrix实现的,具备服务熔断、服务降级、线程和信号隔离、请求缓存、请求合并以及服务监控等强大的功能。

模拟服务宕机故障

分别启动以下Spring Boot项目:

  1. eureka-server-vFinchley.Rc2:服务注册中心。
  2. eureka-client-vFinchley.Rc2:服务提供者,分别以8081和8082端口启动两个实例。
  3. ribbon-consumer-vFinchley.Rc2:消费者。

调用localhost:3333/consumer接口,发现消费者会以轮询的方式调用两个服务提供者,现在关闭8082端口的实例,再次调用接口时会出现以下错误:

Hystris快速实现

第一步,创建项目hystrix-vFinchley.Rc2,勾选如下依赖:

在pom.xml内多了Hystrix的依赖

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

第二步,在主类Application中配置@EnableCircuitBreaker注解开启断路保护功能,你也可以直接使用@SpringCloudApplication注解代替@SpringBootApplication@EnableDiscoveryClient@EnableCircuitBreaker,查看源码会发现@SpringCloudApplication包含了这三个注解。

//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker
@SpringCloudApplication
public class Application {

	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

第三步,创建HelloService,注入RestTemplate实例调用服务并加入@HystrixCommand注解来指定回调方法,添加回调方法。

@Service("helloService")
public class HelloService {
	@Autowired
	private RestTemplate restTemplate;
	
	@HystrixCommand(fallbackMethod="helloFallback")
	public String hello(){
		return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
	}
	
	public String helloFallback(){
		return "error";
	}
}

第四步,创建HelloController并注入HelloService实例并调用hello()方法。

@RestController
public class HelloController {

	@Autowired
	private HelloService helloService;
	
	@GetMapping("hello")
	public String hello(){
		return helloService.hello();
	}
}

第五步,修改配置文件application.yml

spring:
  application:
    name: hystrix #为服务命名
server:
  port: 3334 #指定端口
eureka:
  client:
    service-url: 
      defaultZone: http://localhost:1111/eureka/ #指定服务注册中心位置
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

接下来启动服务注册中心、启动8081和8082端口的hello-service服务实例、启动消费者hystrix。请求localhost:3334/hello接口 ,依然会轮询两个hello-service服务实例,接下来关掉8082端口的服务,当轮询到8082端口的服务实例后不会报错而是返回error。

当然你也可以模拟服务阻塞的情况,断路器默认超时时间为1000ms,我们用代码模拟请求阻塞。

第一步,修改服务提供者hello-service的hello接口,让它随机睡眠0~3000ms,并且打印睡眠的时间。

@RestController
@RequestMapping("hystrix")
public class HystrixController {
	
	@GetMapping("hello")
	public String index(){
		System.out.println("hello");
		try {
			//休眠0-3000ms
			int sleepTime = new Random().nextInt(3000);
			Thread.sleep(sleepTime);
			System.out.println(sleepTime);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "hello";
	}
}

第二步,修改消费者hystrix的HelloService打印调用服务的响应时间。

@HystrixCommand(fallbackMethod="helloFallback")
public String hello(){
	long start = System.currentTimeMillis();
	String result = restTemplate.getForEntity("http://HELLOSERVICE/hystrix/hello",String.class)
                                .getBody();
	long end = System.currentTimeMillis();
	System.out.println(end-start);
	return result;
}

public String helloFallback() {
	return "error";
}

发现每次控制台打印超过1000ms就会返回error,即服务消费者因为调用服务超时从而触发熔断请求,并调用回调逻辑返回结果,这就初步实现了一个简单的断路器。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值