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

论坛 期权论坛 脚本     
匿名技术用户   2021-1-5 05:34   11   0

为什么要用断路器?

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

断路器的作用就是在分布式系统中,当某个服务单元出现故障时,通过断路器的故障监控向服务的调用方返回一个错误响应,而不是长时间的等待(类似电路发生短路,通过断路器熔断保险丝来保障安全)。这样就不会使得线程因为调用故障服务长时间得不到释放,最终蔓延到整个系统导致系统崩溃。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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP