前言
本章不在是像之前的那个一样是配置文件了,本章是一个如何处理雪崩效应的案例。
因为雪崩效应指的是出现在服务端的,所以好好的理解服务端就行。
雪崩效应的概念和原因
雪崩效应
什么是雪崩效应?
其实听起来的话就可能会一知半解的,不就是因为一个点的缺损而导致了问题变得越来越大。
事实上也就是这样。
举个栗子:
1、一个a请求来找服务A的,可服务A还不能解决a请求的需求,这时服务B也接收到了b请求,可这个服务B的处理方式需要服务A来处理一个部分,可是服务A现在还在处理a请求中,无法给服务B一个答复。
2、同时服务A还会在这个时间中还会接收到其他来请求服务A的,所以在请求的积压中服务A挂了,那么就更加无法给服务B一个答复了,所以服务B也一直的卡住,直到宕机
3、同理,如果还有需要依赖服务B的服务C的话,那么。。。
造成原因
原因如下:
常见的导致雪崩的情况有以下几种:
- 程序bug导致服务不可用,或者运行缓慢
- 缓存击穿,导致调用全部访问某服务,导致down掉
- 访问量的突然激增。
- 硬件问题,
额,其实会造成的原因有很多,
使用Hystrix处理策略
这个其实会用就行了,毕竟这是一个完美的一个解决方案,
原理:在服务超过了Hystrix策略的一个时间后,策略将会自动给这个请求降级,额,降级其实就是说,哎呀你要请求的方法无法请求,所以就调用定好的方法,直接返回一个服务器好忙,以达到熔断的效果(就是把这根请求线断掉)
- 1、导入Hystrix依赖
- 2、在要处理方案的服务方上加上@EnableCircuitBreaker
- 3、可以再yml文件修改Hystrix默认的超时时间
Hystrix案例
创建一个服务端来准备模拟测试:microservice-student-provider-hystrix-1004
pom.xml
加了一个Hystrix依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--保持使用版本的一致1.0-SNAPSHOT-->
<parent>
<groupId>com.wxm</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-provider-hystrix-1004</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--相当于全局的一个依赖关系,这个导入能确保整个项目使用的包版本一致
比如全局中的: spring-cloud-dependencies
spring-boot-dependencies
druid-spring-boot-starter
-->
<dependency>
<groupId>com.wxm</groupId>
<artifactId>microservice-common</artifactId>
</dependency>
<!--处理web请求-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--test测试的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用的数据库关系映射框架是jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--使用的是mysql数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--使用tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--需要引入公共模块的实体类等(在导入的时候出现)-->
<dependency>
<groupId>com.wxm</groupId>
<artifactId>microservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!-- actuator监控引入,点击后的追责 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--添加注册中心Eureka相关配置,就是说这个是客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--Hystrix相关依赖,用来处理服务处理异常情况-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件中加了一个Hystrix的一个处理时间策略。
server:
port: 1004
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:2206/test?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application: # 设置应用的基本信息(名称
name: microservice-student
eureka:
instance:
hostname: localhost #eureka客户端主机实例名称
appname: microservice-student #客户端服务名
instance-id: microservice-student:1004 #客户端实例名称
prefer-ip-address: true #是否显示IP
client:
service-url:
#设置与Eureka注册中心交互的地址,是所有注册中心
defaultZone: http://eureka2001.wxm.com:2001/eureka/,http://eureka2002.wxm.com:2002/eureka/,http://eureka2003.wxm.com:2003/eureka/ #把服务注册到eureka注册中心
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
info:
groupId: com.wxm.springcloud
artifactId: microservice-student-provider-1004
version: 1.0-SNAPSHOT
userName: http://www.wxm.com
phone: 123456
启动类StudentProviderHystrixApplication_1004加下注解支持 @EnableCircuitBreaker
package com.wxm.microservicestudentproviderhystrix1004;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.EnableMBeanExport;
@EnableCircuitBreaker
@EnableEurekaClient
@EntityScan("com.wxm.*.*")
@SpringBootApplication
public class MicroserviceStudentProviderHystrix1004Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentProviderHystrix1004Application.class, args);
}
}
respository和service省略代码,复制provider1001就是
重要的Controller层
在下面我们加了一个为hystrix的请求方法
package com.wxm.microservicestudentproviderhystrix1004.controller;
import com.wxm.microservicestudentproviderhystrix1004.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/student")
public class StudentProviderController {
@Value("${server.port}")
private String port;
@Autowired
private StudentService studentService;
@PostMapping(value="/save")
public boolean save(Student student){
try{
studentService.save(student);
return true;
}catch(Exception e){
return false;
}
}
@GetMapping(value="/list")
public List<Student> list(){
return studentService.list();
}
@GetMapping(value="/get/{id}")
public Student get(@PathVariable("id") Integer id){
return studentService.findById(id);
}
@GetMapping(value="/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
try{
studentService.delete(id);
return true;
}catch(Exception e){
return false;
}
}
@RequestMapping("/ribbon")
public String ribbon(){
return "工号【"+port+"】正在为您服务";
}
/**
* 测试Hystrix服务降级
* @return
* @throws InterruptedException
*/
@GetMapping(value="/hystrix")
@HystrixCommand(fallbackMethod="hystrixFallback")
public Map<String,Object> hystrix() throws InterruptedException{
Thread.sleep(3000);
Map<String,Object> map=new HashMap<String,Object>();
map.put("code", 200);
map.put("info","工号【"+port+"】正在为您服务aaaa");
return map;
}
public Map<String,Object> hystrixFallback() throws InterruptedException{
Map<String,Object> map=new HashMap<String,Object>();
map.put("code", 500);
map.put("info", "系统【"+port+"】繁忙,稍后重试");
return map;
}
}
这里我正常访问 返回的是 code=200
但是我们这里Thread.sleep(3000) 模拟超时情况;
这里的话 我们加上@HystrixCommand注解 以及 fallbackMethod
表明这个方法我们再 没有异常以及没有超时(hystrix默认1秒算超时)的情况, 才返回正常的业务数据;
否则,进入我们fallback指定的本地方法,我们搞的是500 系统出错,稍后重试,有效的解决雪崩效应,以及返回给用户界面很好的报错提示信息;
生活举例来更好理解: 就是我们经常会访问网站是会提示网络繁忙,其实也就是使用的这种熔断
注意!!!也要把之前的microservice-student-consumer-80消费者也加上这个请求
/**
* 测试Hystrix服务降级
* @return
*/
@GetMapping(value="/hystrix")
public Map<String,Object> hystrix(){
return restTemplate.getForObject(SERVER_IP_PORT+"/student/hystrix/", Map.class);
}
测试
那么我们就可以根据模拟的休眠时间来模拟一个服务请求超时的问题了。
Hystrix的默认超过时间为1秒。
自己可以修改yml文件Hystrix的时间策略
测试下
先启动三个eureka,再启动带hystrix的provider,最后启动普通的consumer;
因为 Hystrix设立3秒算超时,所有 sleep了3秒 所以进入自定义fallback方法,防止服务雪崩;
Hystrix的服务监听平台Dashboard
重点是可以监控到对应端口号的服务状态
创建一个项目:microservice-student-consumer-hystrix-dashboard-90
pom.xml依赖
只需用到自己所需的依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wxm</groupId>
<artifactId>microservice</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-consumer-hystrix-dashboard-90</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--Hystrix服务监控Dashboard依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件:
server:
port: 90
context-path: /
main
加注解:@EnableHystrixDashboard
package com.wxm.microservicestudentconsumerhystrixdashboard90;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@EnableHystrixDashboard
public class MicroserviceStudentConsumerHystrixDashboard90Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentConsumerHystrixDashboard90Application.class, args);
}
}
我们启动这个项目;
开启后输入自己的一个地址http://localhost:90/hystrix
点击ok就是下面的界面:
总结
1、雪崩的原理
2、处理雪崩的策略:一个解决策略Hystrix
3、服务监控平台: Dashboard
一、什么是雪崩效应?
其实听起来的话就可能会一知半解的,不就是因为一个点的缺损而导致了问题变得越来越大。
事实上也就是这样。
举个栗子:
1、一个a请求来找服务A的,可服务A还不能解决a请求的需求,这时服务B也接收到了b请求,可这个服务B的处理方式需要服务A来处理一个部分,可是服务A现在还在处理a请求中,无法给服务B一个答复。
2、同时服务A还会在这个时间中还会接收到其他来请求服务A的,所以在请求的积压中服务A挂了,那么就更加无法给服务B一个答复了,所以服务B也一直的卡住,直到宕机。
3、同理,如果还有需要依赖服务B的服务C的话,那么。。。
二、处理策略Hystrix
这个其实会用就行了,毕竟这是一个完美的一个解决方案,
原理:在服务超过了Hystrix策略的一个时间后,策略将会自动给这个请求降级,额,降级其实就是说,哎呀你要请求的方法无法请求,所以就调用定好的方法,直接返回一个服务器好忙,以达到熔断的效果(就是把这根请求线断掉)
1、导入Hystrix依赖
2、在要处理方案的服务方上加上@EnableCircuitBreaker
3、可以再yml文件修改Hystrix默认的超时时间
三、服务监控平台
这个没什么好讲的,重点是可以监控到对应端口号的服务状态
总结:本次的操作很简单,要点是了解雪崩效应并处理