4.Spring Cloud Hystrix服务容错保护

Spring Cloud Hystrix

Spring Cloud Hystrix提供了容错保护机制,依赖信息是:

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

1.demo程序,体验hystrix

创建多模块聚合工程。

父工程

新建一个父工程cloud02,依赖信息如下:

<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>
	<groupId>com.cloud</groupId>
	<artifactId>cloud02</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<!--spring boot依赖管理,Spring cloud是建立在Spring boot之上的-->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
	</parent>

	<dependencyManagement>
		<!--spring cloud 的依赖管理-->
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Greenwich.RC1</version>
				<scope>import</scope>
				<type>pom</type>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<repositories>
	<!--Spring Milestones仓库-->
   <repository>
         <id>spring-milestones</id>
         <name>Spring Milestones</name>
         <url>https://repo.spring.io/milestone</url>
     </repository>
 </repositories>
<!--这个modules是在创建了子模块后生成的,不是创建父工程时创建的,注意!-->
<modules>
	<module>cloud02-eureka-server</module>
	<module>cloud02-eureka-client</module>
	<module>cloud02-eureka-consumer</module>
</modules>
</project>

注册中心

新建一个子模块cloud02-eureka-server作为注册中心,依赖信息如下:

<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>
  <parent>
    <groupId>com.cloud</groupId>
    <artifactId>cloud02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>cloud02-eureka-server</artifactId>
  
  <dependencies>
  	<!--作为注册中心要导入spring-cloud-starter-netflix-eureka-server依赖-->
  	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  	</dependency>
  </dependencies>
  
</project>

配置文件信息如下:


spring:
  application:
  # 配置应用名称
    name: eureka-server
    
eureka:
  server:
  # 关闭保护机制,关于保护机制 在eureka文章中有提到
    enable-self-preservation: false
  client:
  	# 不获取注册信息
    fetch-registry: false
    # 不把自己注册到注册中心
    register-with-eureka: false
   # 配置当前项目端口,当前项目作为注册中心,也就是注册中心的端口
server:
  port: 8070

启动类:

@SpringBootApplication
// 开始EurekaServer(注册中心)功能
@EnableEurekaServer
public class EurekaServerApp {

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

注册中心创建完毕,启动项目启动注册中心!

客户端-提供服务

新建一个cloud02-eureka-client模块,这个客户端用于提供服务,pom.xml文件如下:

<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>
	<parent>
		<groupId>com.cloud</groupId>
		<artifactId>cloud02</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>cloud02-eureka-client</artifactId>

	<dependencies>
		<!--作为客户端要导入spring-cloud-starter-netflix-eureka-client依赖-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<!--用于构建web项目-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

配置信息(application.yml):


server:
# 当前项目端口
  port: 8090

spring:
  application:
  # 项目名
    name: eureka-client

eureka:
  client:
    service-url:
    # 配置注册中心信,要注册到哪个注册中心
      defaultZone: http://localhost:8070/eureka/

启动类:

@SpringBootApplication
// 作为客户端一定要开启EnableDiscoveryClient
@EnableDiscoveryClient
public class EurekaClientApp {
	
	public static void main(String[] args) {
		SpringApplication.run(EurekaClientApp.class, args);
	}

}

服务接口(用户提供给其他服务调用):

@RestController
public class HelloController {

	@GetMapping("/hello")
	public String getHello() {
		return "hello eureka";
	}
	
}

客户端-消费服务

新建一个模块cloud02-eureka-consumer,来消费cloud02-eureka-client提供的/hello服务。pom.xml文件如下:

<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>
  <parent>
    <groupId>com.cloud</groupId>
    <artifactId>cloud02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>cloud02-eureka-consumer</artifactId>
  
  <dependencies>
  	<!--消费服务也是一个Eureka Client-->
  	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  	</dependency>
  	<!--提供web支持,作为web项目-->
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>
  	<!--导入断路器支持 hystrix-->
  	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  	</dependency>
  </dependencies>
  
</project>

配置信息(application.yml):

# 配置项目的名称
spring:
  application:
    name: eureka-consumer

server:
# 配置 项目的端口
  port: 8091
 

eureka:
  client:
    service-url:
    # 配置注册中心 当前项目要发不到注册中心(从注册中心获取注册信息)
      defaultZone: http://localhost:8070/eureka/
 

启动类:

@SpringBootApplication
// 这是一个客户端程序
@EnableDiscoveryClient
// 开启断路器支持
@EnableCircuitBreaker
public class EurekaConsumerApp {
	
	// 注册RestTemplate 
	@Bean
	// 开启客户端负载均衡
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

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

@EnableDiscoveryClient@SpringBootApplication@EnableCircuitBreaker也可以使用@SpringCloudApplication代替。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication // 包含了@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

新建controller:

@RestController
public class HiController {

	@Autowired
	private HiService hiService;
	
	
	@GetMapping("/consumer")
	public String getHello() {
		String hello = hiService.getHello();
		return "result: " + hello;
	}
	
}

controller中调用了**HiService **,HiService中的代码:

@Service
public class HiService {
	
	@Autowired
	private RestTemplate restTemplate;
	
	// @HystrixCommand做断路处理,fallbackMethod:如果调用服务出错就会调用这个属性指向的方法
	@HystrixCommand(fallbackMethod = "fallbackHello")
	public String getHello() {
		// 这里调用服务,直接使用服务名即可
		ResponseEntity<String> response = restTemplate.getForEntity("http://eureka-client/hello", String.class);
		return response.getBody();
	}
	
	public String fallbackHello() {
		return "err";
	}

}

@HystrixCommand做断路处理表示这个请求中调用服务如果出错会被处理,fallbackMethod:如果调用服务出错就会调用这个属性指向的方法。
所以在访问上面项目的/consumer接口时,如果eureka-client不能被访问(比如eureka-client被关闭了),那么这个就会调用fallbackHello方法,返回err。

2.概念

服务降级

如果请求需要的服务得不到响应,就降级去请求另一个服务,如果另一个服务得不到响应再去请求其他服务,依次类推,直到有一个满足的服务,不应该有错误存在。
@HystrixCommand(fallbackMethod = “fallbackHello”),以此为例,当@HystrixCommand注解所标记的方法中抛出异常等情况,回去调用fallbackMethod 指向的方法,而fallbackMethod 方法最终放回一个接口给调用者。那么这就是服务降级,简单的理解就是当前服务获取有问题,导致不能得到结果,那么就降级不获取这个服务,而从其他地方获取,这个其他地方也应该获取一个由保障的数据(比如降级服务还是获取一个服务(或者网络请求)就应该继续使用@HystrixCommand…)

雪崩效应

简单来说雪崩效应是被依赖的服务出错,导致当前服务出错,当前服务出错又导致依赖当前服务的服务出错,从而导致整个系统出错。
例如一个请求长时间得不到响应,那么这个请求对应的线程资源就得不到释放,长时间多个请求进来,就会消耗尽服务器资源。从而导致系统崩溃。

断路器

断路器就是保护应用程序的一种手段,如果每次调用都会放回一个错误的代码(请求报错),报错导致程序无法处理,此时可以断路器打开,这个请求将不在被执行,而是直接返回错误信息。过一段时间后,断路器处于半打开状态,会放行部分请求,如果这部分请求,请求成功的话,断路器关闭。

猜你喜欢

转载自blog.csdn.net/qq122516902/article/details/85071306