服务雪崩效应
当一个请求依赖多个服务的时候:
正常情况下的访问
但是,当请求的服务中出现无法访问、异常、超时等问题时(图中的I),那么用户的请求将会被阻塞。
如果多个用户的请求中,都存在无法访问的服务,那么他们都将陷入阻塞的状态中。
Hystrix的引入,可以
服务熔断服务降级
Hystrix断路器简介
hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,
这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo。
通过服务熔断和服务降级来解决这个问题。
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,
这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
Hystrix服务熔断服务降级@HystrixCommand fallbackMethod
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当某个服务不可用或者响应时间超时,会进行服务降级,进而熔断该节点的服务调用,快速返回自定义的错误影响页面信息。
新j建的带服务熔断的服务提供者项目
microservice-student-provider-hystrix-1004
配置pom.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>com.javaqi</groupId> 7 <artifactId>qimicroservice</artifactId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <artifactId>microservice-student-provider-hystrix-1004</artifactId> 11 12 <properties> 13 <java.version>1.8</java.version> 14 </properties> 15 16 <dependencies> 17 <dependency> 18 <groupId>com.javaqi</groupId> 19 <artifactId>microservice-common</artifactId> 20 </dependency> 21 <dependency> 22 <groupId>org.springframework.boot</groupId> 23 <artifactId>spring-boot-starter-web</artifactId> 24 </dependency> 25 <dependency> 26 <groupId>org.springframework.boot</groupId> 27 <artifactId>spring-boot-starter-test</artifactId> 28 <scope>test</scope> 29 </dependency> 30 <dependency> 31 <groupId>org.springframework.boot</groupId> 32 <artifactId>spring-boot-starter-data-jpa</artifactId> 33 </dependency> 34 <dependency> 35 <groupId>mysql</groupId> 36 <artifactId>mysql-connector-java</artifactId> 37 </dependency> 38 <dependency> 39 <groupId>org.springframework.boot</groupId> 40 <artifactId>spring-boot-starter-tomcat</artifactId> 41 </dependency> 42 <dependency> 43 <groupId>com.alibaba</groupId> 44 <artifactId>druid-spring-boot-starter</artifactId> 45 </dependency> 46 <!-- 修改后立即生效,热部署 --> 47 <dependency> 48 <groupId>org.springframework</groupId> 49 <artifactId>springloaded</artifactId> 50 </dependency> 51 <dependency> 52 <groupId>org.springframework.boot</groupId> 53 <artifactId>spring-boot-devtools</artifactId> 54 </dependency> 55 56 <!--添加注册中心Eureka相关配置--> 57 <dependency> 58 <groupId>org.springframework.cloud</groupId> 59 <artifactId>spring-cloud-starter-eureka</artifactId> 60 </dependency> 61 <dependency> 62 <groupId>org.springframework.cloud</groupId> 63 <artifactId>spring-cloud-starter-config</artifactId> 64 </dependency> 65 <dependency> 66 <groupId>com.javaqi</groupId> 67 <artifactId>microservice-common</artifactId> 68 <version>1.0-SNAPSHOT</version> 69 <scope>compile</scope> 70 </dependency> 71 72 <!-- actuator监控引入 --> 73 <dependency> 74 <groupId>org.springframework.boot</groupId> 75 <artifactId>spring-boot-starter-actuator</artifactId> 76 </dependency> 77 78 <!--Hystrix相关依赖--> 79 <dependency> 80 <groupId>org.springframework.cloud</groupId> 81 <artifactId>spring-cloud-starter-hystrix</artifactId> 82 </dependency> 83 <dependency> 84 <groupId>com.javaqi</groupId> 85 <artifactId>microservice-student-provider</artifactId> 86 <version>1.0-SNAPSHOT</version> 87 <scope>compile</scope> 88 </dependency> 89 90 </dependencies> 91 92 <build> 93 <plugins> 94 <plugin> 95 <groupId>org.springframework.boot</groupId> 96 <artifactId>spring-boot-maven-plugin</artifactId> 97 </plugin> 98 </plugins> 99 </build> 100 101 </project>
l修改application.yml
1 server: 2 port: 1004 3 context-path: / 4 spring: 5 datasource: 6 type: com.alibaba.druid.pool.DruidDataSource 7 driver-class-name: com.mysql.jdbc.Driver 8 url: jdbc:mysql://localhost:3306/xufanqi?useUnicode=true&characterEncoding=utf8 9 username: root 10 password: 123 11 jpa: 12 hibernate: 13 ddl-auto: update 14 show-sql: true 15 application: 16 name: microservice-student 17 profiles: provider-hystrix-1004 18 19 eureka: 20 instance: 21 hostname: localhost 22 appname: microservice-student 23 instance-id: microservice-student:1004 24 prefer-ip-address: true 25 client: 26 service-url: 27 defaultZone: http://eureka2001.javaqi.com:2001/eureka/,http://eureka2002.javaqi.com:2002/eureka/,http://eureka2003.javaqi.com:2003/eureka/ 28 29 hystrix: 30 command: 31 default: 32 execution: 33 isolation: 34 thread: 35 timeoutInMilliseconds: 3000 36 info: 37 groupId: com.javaxl.testSpringcloud 38 artifactId: microservice-student-provider-hystrix-1004 39 version: 1.0-SNAPSHOT 40 userName: http://javaqi.com 41 phone: 123456
StudentProviderHystrixApplication_1004加下注解支持
@EnableCircuitBreaker
1 package com.javaqi.microservicestudentproviderhystrix1004; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.boot.autoconfigure.domain.EntityScan; 6 import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 9 @EnableCircuitBreaker 10 @EntityScan("com.javaqi.*.*") 11 @EnableEurekaClient 12 @SpringBootApplication 13 public class MicroserviceStudentProviderHystrix1004Application { 14 15 public static void main(String[] args) { 16 SpringApplication.run(MicroserviceStudentProviderHystrix1004Application.class, args); 17 } 18 19 }
controller
服务提供者1004中新增
StudentProviderController
1 package com.javaqi.microservicestudentproviderhystrix1004.controller; 2 3 import com.javaqi.microservicecommon.entity.Student; 4 import com.javaqi.microservicestudentproviderhystrix1004.service.StudentService; 5 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Value; 8 import org.springframework.web.bind.annotation.*; 9 10 import java.util.HashMap; 11 import java.util.List; 12 import java.util.Map; 13 14 @RestController 15 @RequestMapping("/student") 16 public class StudentProviderController { 17 18 @Autowired 19 private StudentService studentService; 20 21 @Value("${server.port}") 22 private String port; 23 24 @PostMapping(value="/save") 25 public boolean save(Student student){ 26 try{ 27 studentService.save(student); 28 return true; 29 }catch(Exception e){ 30 return false; 31 } 32 } 33 34 @GetMapping(value="/list") 35 public List<Student> list(){ 36 return studentService.list(); 37 } 38 39 @GetMapping(value="/get/{id}") 40 public Student get(@PathVariable("id") Integer id){ 41 return studentService.findById(id); 42 } 43 44 @GetMapping(value="/delete/{id}") 45 public boolean delete(@PathVariable("id") Integer id){ 46 try{ 47 studentService.delete(id); 48 return true; 49 }catch(Exception e){ 50 return false; 51 } 52 } 53 54 @RequestMapping("/ribbon") 55 public String ribbon(){ 56 return "工号【"+port+"】正在为您服务"; 57 } 58 59 60 61 /** 62 * 测试Hystrix服务降级 63 * @return 64 * @throws InterruptedException 65 */ 66 @ResponseBody 67 @GetMapping(value="/hystrix") 68 @HystrixCommand(fallbackMethod="hystrixFallback") 69 public Map<String,Object> hystrix() throws InterruptedException{ 70 Thread.sleep(4000); 71 Map<String,Object> map=new HashMap<String,Object>(); 72 map.put("code", 200); 73 map.put("info","工号【"+port+"】正在为您服务"); 74 return map; 75 } 76 77 public Map<String,Object> hystrixFallback() throws InterruptedException{ 78 Map<String,Object> map=new HashMap<String,Object>(); 79 map.put("code", 500); 80 map.put("info", "系统【"+port+"】繁忙,稍后重试"); 81 return map; 82 } 83 }
这里正常访问 返回的是 200 业务数据xxxxx
但是我们这里Thread.sleep(2000) 模拟超时;
这里的话 我们加上@HystrixCommand注解 以及 fallbackMethod
表明这个方法我们再 没有异常以及没有超时(hystrix默认1秒算超时)的情况,才返回正常的业务数据;
否则,进入我们fallback指定的本地方法,我们搞的是500 系统出错,稍后重试,有效的解决雪崩效应,以及返回给用户界面
很好的报错提示信息;
microservice-student-consumer-80项目也要对应的加个方法
1 package com.javaqi.microservicestudentconsumerfeign80.controller; 2 3 import com.javaqi.microservicecommon.entity.Student; 4 import com.javaqi.microservicecommon.service.StudentClientService; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.web.bind.annotation.*; 7 import org.springframework.web.client.RestTemplate; 8 9 import java.util.List; 10 11 @RestController 12 @RequestMapping("/student") 13 public class StudentConsumerController { 14 15 @Autowired 16 private StudentClientService studentClientService; 17 18 @Autowired 19 private RestTemplate restTemplate; 20 21 @PostMapping(value = "/save") 22 private boolean save(Student student) { 23 return studentClientService.save(student); 24 } 25 26 @GetMapping(value = "/list") 27 public List<Student> list() { 28 return studentClientService.list(); 29 } 30 31 @GetMapping(value = "/get/{id}") 32 public Student get(@PathVariable("id") Integer id) { 33 return studentClientService.get(id); 34 } 35 36 @GetMapping(value = "/delete/{id}") 37 public boolean delete(@PathVariable("id") Integer id) { 38 try { 39 studentClientService.delete(id); 40 return true; 41 } catch (Exception e) { 42 return false; 43 } 44 } 45 46 @RequestMapping("/ribbon") 47 public String ribbon(){ 48 return studentClientService.ribbon(); 49 } 50 }
先启动三个eureka,再启动带hystrix的provider,最后启动普通的consumer;
因为 Hystrix默认1算超时,所有 sleep了2秒 所以进入自定义fallback方法,防止服务雪崩;
我们这里改sleep修改成100毫秒;
Hystrix默认超时时间设置
Hystrix默认超时时间是1秒,我们可以通过hystrix源码看到,
找到 hystrix-core.jar com.netflix.hystrix包下的HystrixCommandProperties类
default_executionTimeoutInMilliseconds属性局势默认的超时时间
默认1000毫秒 1秒
我们系统里假如要自定义设置hystrix的默认时间的话;
application.yml配置文件加上
改成3秒 然后 我们代码里sleep修改成2秒测试;
sleep修改成4秒;
Hystrix服务监控Dashboard
Hystrix服务监控Dashboard仪表盘
Hystrix提供了 准实时的服务调用监控项目Dashboard,能够实时记录通过Hystrix发起的请求执行情况,
可以通过图表的形式展现给用户看。
我们新建项目:
microservice-student-consumer-hystrix-dashboard-90
pom
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>com.javaqi</groupId> 7 <artifactId>qimicroservice</artifactId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <artifactId>microservice-student-consumer-hystrix-dashboard-90</artifactId> 11 12 <properties> 13 <java.version>1.8</java.version> 14 </properties> 15 16 <dependencies> 17 <dependency> 18 <groupId>org.springframework.boot</groupId> 19 <artifactId>spring-boot-starter</artifactId> 20 </dependency> 21 22 <dependency> 23 <groupId>org.springframework.boot</groupId> 24 <artifactId>spring-boot-starter-test</artifactId> 25 <scope>test</scope> 26 <exclusions> 27 <exclusion> 28 <groupId>org.junit.vintage</groupId> 29 <artifactId>junit-vintage-engine</artifactId> 30 </exclusion> 31 </exclusions> 32 </dependency> 33 34 <!--Hystrix服务监控Dashboard依赖--> 35 <dependency> 36 <groupId>org.springframework.cloud</groupId> 37 <artifactId>spring-cloud-starter-hystrix</artifactId> 38 </dependency> 39 <dependency> 40 <groupId>org.springframework.cloud</groupId> 41 <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> 42 </dependency> 43 <dependency> 44 <groupId>org.springframework.boot</groupId> 45 <artifactId>spring-boot-starter-actuator</artifactId> 46 </dependency> 47 48 </dependencies> 49 50 <build> 51 <plugins> 52 <plugin> 53 <groupId>org.springframework.boot</groupId> 54 <artifactId>spring-boot-maven-plugin</artifactId> 55 </plugin> 56 </plugins> 57 </build> 58 59 </project>
配置application.yml
1 server: 2 port: 90 3 servlet: 4 context-path: /
启动类:StudentConsumerDashBoardApplication_90
加注解:@EnableHystrixDashboard
1 package com.javaqi.microservicestudentconsumerhystrixdashboard90; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 6 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; 7 import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 8 9 @SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) 10 @EnableHystrixDashboard 11 public class MicroserviceStudentConsumerHystrixDashboard90Application { 12 13 public static void main(String[] args) { 14 SpringApplication.run(MicroserviceStudentConsumerHystrixDashboard90Application.class, args); 15 } 16 17 }
启动
启动三个eureka,然后再启动microservice-student-provider-hystrix-1004
直接请求http://localhost:1004/student/hystrix
指标含义:
各种情况: