spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

网友投稿 220 2023-02-06


spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖。但是如果有一些服务出现问题了会怎么样?

比如说有三个服务(ABC),A调用B,B调用C。由于网络延迟或C本身代码有问题导致B迟迟得不到回应,这样B调用C的请求就会被挂起,等待。

在高并发的访问的情况下,这些挂起的线程得不到释放,使后续的请求阻塞,最终导致B也挂掉

http://

了。依次类

CPPcIaKFY

推,A可能也会挂掉,进而使整个系统全部崩溃。

为了解决整个问题,Spring Cloud 使用Hystrix进行服务容错保护,包括断路器、线程隔离等一系列的保护功能,今天我们就来看下如何通过Hystrix实现断路器。

一、什么是Spring Cloud Hystrix?什么是断路器?

Spring Cloud Hystrix是基于Netflix的开源框架Hystrix实现的,其目的是为了通过控制那些访问远程系统、服务和第三方的节点,从而对延迟和故障提供强大的容错能力。

断路器类似于我们家里面强电箱里面用到的漏电断路保护器,当服务单元出现故障(类似于电器发生短路),通过断路器的故障监控功能(类似于保险丝),向调用方返回一个错误响应,避免长时间等待,从而避免故障蔓延到整个系统。

二、没有断路器的情况下,页面展示

还记得我们前面写的spring cloud 入门系列二:使用Eureka 进行服务治理里面的三个服务(eureka/hello-service/hello-consumer)吗?我们基于这个进行实验。

1.启动eureka服务

http://

注册中心,端口号1111

2.启动hello-service服务提供者,这里我们启动两个服务,端口号分别为9090,9091

3.启动hello-consumer服务消费者,端口号为9999;这个时候我们多次访问http://localhost:9999/hello-consumer是没有问题的

4.将hello-service端口号为9091的服务关掉,再去多次访问http://localhost:9999/hello-consumer,报错了

PS:这里说明下,为什么要多次访问,是因为我们通过ribbon实现了负载均衡,访问http://localhost:9999/hello-consumer的时候,会轮询访问hello-service的两个服务,当访问到端口号是9091的服务时才报错,访问9090的服务就不会有问题。

三、断路器代码实现

接下来我们看下如何进行代码实现,我们不去修改服务注册中心和服务提供者,只需要修改服务消费者hello-consumer。

1.修改POM文件,引入Hystrix依赖

xmlns:xsi="http://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">

4.0.0

com.sam

hello-consumer

0.0.1-SNAPSHOT

org.springframework.boot

spring-boot-starter-parent

1.5.1.RELEASE

1.8

org.springframework.cloud

spring-cloudhttp://-dependencies

Camden.SR6

pom

import

org.springframework.cloud

spring-cloud-starter-eureka

org.springframework.cloud

spring-cloud-starter-ribbon

org.springframework.cloud

spring-cloud-starter-hystrix

xmlns:xsi="http://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">

4.0.0

com.sam

hello-consumer

0.0.1-SNAPSHOT

org.springframework.boot

spring-boot-starter-parent

1.5.1.RELEASE

1.8

org.springframework.cloud

spring-cloudhttp://-dependencies

Camden.SR6

pom

import

org.springframework.cloud

spring-cloud-starter-eureka

org.springframework.cloud

spring-cloud-starter-ribbon

org.springframework.cloud

spring-cloud-starter-hystrix

2.修改启动类,追加注解@EnableCircuitBreaker,开启断路器

@EnableDiscoveryClient

@SpringBootApplication

@EnableCircuitBreaker

public class ConsumerApp {

//@Bean 应用在方法上,用来将方法返回值设为为bean

@Bean

@LoadBalanced //@LoadBalanced实现负载均衡

public RestTemplate restTemplate() {

return new RestTemplate();

}

public static void main(String[] args) {

SpringApplication.run(ConsumerApp.class, args);

}

}

这个时候你会发现,这个启动类加了三个注解,这个是不是很麻烦?没关系,我们可以使用注解@SpringCloudApplication

@SpringCloudApplication

public class ConsumerApp {

//@Bean 应用在方法上,用来将方法返回值设为为bean

@Bean

@LoadBalanced //@LoadBalanced实现负载均衡

public RestTemplate restTemplate() {

return new RestTemplate();

}

public static void main(String[] args) {

SpringApplication.run(ConsumerApp.class, args);

}

}

@SpringCloudApplication = @EnableDiscoveryClient +@SpringBootApplication+@EnableCircuitBreaker,从源码就能看出来:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootApplication

@EnableDiscoveryClient

@EnableCircuitBreaker

public @interface SpringCloudApplication {

}

3.追加service

@Service

public class ConsumerService {

@Autowired

RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "errorMsg")

public String consumer() {

// 调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port

restTemplate.getForObject("http://hello-service/hello", String.class);

http://return "hello consumer finish !!!";

}

public String errorMsg() {

return "error!!!";

}

}

我们把原来controller里面的调用RestTemplate的实现放到service里面,并且通过@HystrixCommand来指定回调方法,当出现错误时调用该方法。

4.修改controller

/**

*这里不再直接调用restTemplate,

*而是通过调用service进行实现

*

*/

@RestController

public class ConsumerController {

@Autowired

// RestTemplate restTemplate;

ConsumerService service;

@RequestMapping("/hello-consumer")

public String helloConsumer() {

// //调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port

// restTemplate.getForObject("http://hello-service/hello", String.class);

return service.consumer();

}

}

5.测试,多次访问,当报错的时候,会显示如下内容


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Vue波纹按钮组件制作
下一篇:spring cloud 使用Eureka 进行服务治理方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~