在微服务架构中,服务众多,通常会涉及到多个服务层的调用,一旦基础服务发生故障,很可能会导致级联故障,继而造成整个系统不可用,这种现象被称为服务雪崩效应。
服务熔断引入熔断器概念,熔断器如果在一段时间内侦测到许多类似错误,就会强迫其以后的多个调用快速失败,不在访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使应用程序继续执行而不用等待修正错误或者浪费CPU时间去等到长时间的超市产生。熔断器也会侦测诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
Hystrix特性
当Hystrix Command名请求后端服务失败数量超过一定高比例(默认50%),断路器切换到开路状态(open);这时所有的请求会直接失败二不会发送到后端服务;断路器保持在开路状态一段时间后(默认为5s),自动切换到半开路状态(Half-open),这是会判断一下请求的返回情况,如果请求成功,则切换回闭路状态(closed),否则切换回开库装填(open)。
Fallback
当请求的后端服务出现异常时,可以使用fallback方法的范围值作为后端服务的返回值。
下面我们以前文创建的Springboot-LoadBalance-producer1、Springboot-LoadBalance-producer2作为项目的基础服务端,并创建服务消费者项目,命名为Springboot-LoadBalance-consumer3,项目创建详细步骤如下:
1、利用MyEclipse创建web project工程Springboot-LoadBalance-consumer3
2、Pom.xml
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--spring-boot-admin-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.0.4</version>
</dependency>
<!--consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--test-->
<!--actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- spring-cloud-config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- bus-amqp -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3、Bootstrap.yml
注意,该配置使用了注册中心,配置中心的搭建工作,学友们可关注博主,到博主博文中查找对应的博文。
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
serviceName: mango-consumer # 注册到consul的服务名称
config:
discovery:
enabled: true # 开启服务发现
serviceId: mango-config # 配置中心服务名称
name: mango-consumer # 对应{application}部分
profile: dev # 对应{profile}部分
#label: master # 对应git的分支,如果配置中心使用的是本地存储,则该参数无用
4、mango-consumer.xml
server:
port: 8006
spring:
application:
name: mango-consumer
boot:
admin:
client:
instance:
service-base-url: ${spring.application.name}
# 开放健康检查接口
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
#开启熔断器
feign:
hystrix:
enabled: true
5、启动函数
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class MangoConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(MangoConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 此配置是为了服务监控而配置,与服务容错本身无关,
// ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
// 只要在自己的项目里配置上下面的servlet就可以了
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
6、添加controller
(1)添加接口程序
@FeignClient(name = "mango-producer", fallback = MangoProducerHystrix.class)
public interface MangoProducerService {
@RequestMapping("/hello")
public String hello();
}
(2)添加MangoProducerHystrix.java
注册服务调用失败时,fallback返回内容
@Component
public class MangoProducerHystrix implements MangoProducerService {
@RequestMapping("/hello")
public String hello() {
return "sorry, hello service call failed.";
}
}
(3)添加controller
@RestController
public class FeignHelloController {
@Autowired
private MangoProducerService mangoProducerService;
@RequestMapping("/feign/call")
public String call() {
// 像调用本地服务一样
return mangoProducerService.hello();
}
}
7、测试项目:
- 首先启动服务注册consul服务;
- 启动配置中心
- 启动Springboot-LoadBalance-producer1、Springboot-LoadBalance-producer2
- 启动新创建的工程Springboot-LoadBalance-consumer3
- 通过http://localhost:8500, 查看仙姑启动情况,如下图所示:
- 通过http://localhost:8006/feign/call,调用后台服务
连续两次访问,实现了负载平衡的轮询算法。下面我们关闭Springboot-LoadBalance-producer1和Springboot-LoadBalance-producer2服务,查看是否能够实现fallback提示信息
备注:Springboot-LoadBalance-producer1和Springboot-LoadBalance-producer2两个工程使用了同一个工程名称,属于同一个项目的两个实例,由于项目使用了负载均衡资质,如果只是关闭其中一个服务,负载平衡机制会自动访问在线的服务,不会返回fallback定义的信息,请注意!