熔断器Hystrix及服务监控Dashboard
服务雪崩效应
当一个请求依赖多个服务的时候:
正常情况下的访问
但是,当请求的服务中出现无法访问、异常、超时等问题时(图中的I),那么用户的请求将会被阻塞。
如果多个用户的请求中,都存在无法访问的服务,那么他们都将陷入阻塞的状态中。
Hystrix的引入,可以通过服务熔断和服务降级来解决这个问题。
服务熔断服务降级
Hystrix断路器简介
hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,
这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo。
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,
这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
Hystrix服务熔断服务降级@HystrixCommand fallbackMethod
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当某个服务不可用或者响应时间超时,会进行服务降级,进而熔断该节点的服务调用,快速返回自定义的错误影响页面信息。
我们写个项目来测试下;
我们写一个新的带服务熔断的服务提供者项目 microservice-student-provider-hystrix-1004
把 配置和 代码 都复制一份到这个项目里;
然后修改;
1,pom.xml加下 hystrix支持
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.yuan</groupId> 7 <artifactId>t226microservice</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 <dependencies> 16 <dependency> 17 <groupId>org.springframework.boot</groupId> 18 <artifactId>spring-boot-starter-web</artifactId> 19 </dependency> 20 <dependency> 21 <groupId>org.springframework.boot</groupId> 22 <artifactId>spring-boot-starter-test</artifactId> 23 <scope>test</scope> 24 </dependency> 25 <dependency> 26 <groupId>org.springframework.boot</groupId> 27 <artifactId>spring-boot-starter-data-jpa</artifactId> 28 </dependency> 29 <dependency> 30 <groupId>mysql</groupId> 31 <artifactId>mysql-connector-java</artifactId> 32 </dependency> 33 <dependency> 34 <groupId>org.springframework.boot</groupId> 35 <artifactId>spring-boot-starter-tomcat</artifactId> 36 </dependency> 37 <dependency> 38 <groupId>com.alibaba</groupId> 39 <artifactId>druid-spring-boot-starter</artifactId> 40 </dependency> 41 <!-- 修改后立即生效,热部署 --> 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>springloaded</artifactId> 45 </dependency> 46 <dependency> 47 <groupId>org.springframework.boot</groupId> 48 <artifactId>spring-boot-devtools</artifactId> 49 </dependency> 50 <dependency> 51 <groupId>com.yuan</groupId> 52 <artifactId>microservice-common</artifactId> 53 <version>1.0-SNAPSHOT</version> 54 <scope>compile</scope> 55 </dependency> 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 <!-- actuator监控引入 --> 66 <dependency> 67 <groupId>org.springframework.boot</groupId> 68 <artifactId>spring-boot-starter-actuator</artifactId> 69 </dependency> 70 <dependency> 71 <groupId>com.yuan</groupId> 72 <artifactId>microservice-student-provider-1001</artifactId> 73 <version>1.0-SNAPSHOT</version> 74 <scope>compile</scope> 75 </dependency> 76 <!--Hystrix相关依赖--> 77 <dependency> 78 <groupId>org.springframework.cloud</groupId> 79 <artifactId>spring-cloud-starter-hystrix</artifactId> 80 </dependency> 81 <dependency> 82 <groupId>com.yuan</groupId> 83 <artifactId>microservice-student-provider</artifactId> 84 <version>1.0-SNAPSHOT</version> 85 <scope>compile</scope> 86 </dependency> 87 88 </dependencies> 89 <build> 90 <plugins> 91 <plugin> 92 <groupId>org.springframework.boot</groupId> 93 <artifactId>spring-boot-maven-plugin</artifactId> 94 </plugin> 95 </plugins> 96 </build> 97 98 </project>
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/j2ee?useUnicode=true&characterEncoding=utf8 9 username: root 10 password: 12345 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.yuan.com:2001/eureka/,http://eureka2002.yuan.com:2002/eureka/,http://eureka2003.yuan.com:2003/eureka/ 28 29 info: 30 groupId: com.yuan.testSpringcloud 31 artifactId: microservice-student-provider-hystrix-1004 32 version: 1.0-SNAPSHOT 33 userName: http://yuan.com 34 phone: 123456
启动类StudentProviderHystrixApplication_1004加下注解支持 @EnableCircuitBreaker
1 package com.yuan.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.yuan.*.*") 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 }
4,服务提供者1004中controller新增
1 package com.yuan.microservicestudentproviderhystrix1004.controller; 2 3 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 import com.yuan.microservicecommon.entity.Student; 5 import com.yuan.microservicestudentproviderhystrix1004.service.StudentService; 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 * 测试Hystrix服务降级 61 * @return 62 * @throws InterruptedException 63 */ 64 @ResponseBody 65 @GetMapping(value="/hystrix") 66 @HystrixCommand(fallbackMethod="hystrixFallback") 67 public Map<String,Object> hystrix() throws InterruptedException{ 68 // Thread.sleep(2000); 69 Map<String,Object> map=new HashMap<String,Object>(); 70 map.put("code", 200); 71 map.put("info","工号【"+port+"】正在为您服务"); 72 return map; 73 } 74 75 public Map<String,Object> hystrixFallback() throws InterruptedException{ 76 Map<String,Object> map=new HashMap<String,Object>(); 77 map.put("code", 500); 78 map.put("info", "系统【"+port+"】繁忙,稍后重试"); 79 return map; 80 } 81 82 }
这里正常访问 返回的是 200 业务数据xxxxx
但是我们这里Thread.sleep(2000) 模拟超时;
这里的话 我们加上@HystrixCommand注解 以及 fallbackMethod
表明这个方法我们再 没有异常以及没有超时(hystrix默认1秒算超时)的情况,才返回正常的业务数据;
否则,进入我们fallback指定的本地方法,我们搞的是500 系统出错,稍后重试,有效的解决雪崩效应,以及返回给用户界面
很好的报错提示信息;
microservice-student-consumer-80项目也要对应的加个方法
1 package com.yuan.microservicestudentconsumer80.controller; 2 3 import com.yuan.microservicecommon.entity.Student; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.*; 6 import org.springframework.web.client.RestTemplate; 7 8 import java.util.List; 9 import java.util.Map; 10 11 @RestController 12 @RequestMapping("/student") 13 public class StudentConsumerController { 14 15 private final static String SERVER_IP_PORT = "http://MICROSERVICE-STUDENT"; 16 17 @Autowired 18 private RestTemplate restTemplate; 19 20 @PostMapping(value="/save") 21 private boolean save(Student student){ 22 return restTemplate.postForObject(SERVER_IP_PORT+"/student/save", student, Boolean.class); 23 } 24 25 @GetMapping(value="/list") 26 public List<Student> list(){ 27 return restTemplate.getForObject(SERVER_IP_PORT+"/student/list", List.class); 28 } 29 30 @GetMapping(value="/get/{id}") 31 public Student get(@PathVariable("id") Integer id){ 32 return restTemplate.getForObject(SERVER_IP_PORT+"/student/get/"+id, Student.class); 33 } 34 35 @GetMapping(value="/delete/{id}") 36 public boolean delete(@PathVariable("id") Integer id){ 37 try{ 38 restTemplate.getForObject(SERVER_IP_PORT+"/student/delete/"+id, Boolean.class); 39 return true; 40 }catch(Exception e){ 41 return false; 42 } 43 } 44 @RequestMapping("/ribbon") 45 public String ribbon(){ 46 return restTemplate.getForObject(SERVER_IP_PORT + "/student/ribbon", String.class); 47 } 48 49 /** 50 * 测试Hystrix服务降级 51 * @return 52 */ 53 @GetMapping(value="/hystrix") 54 @ResponseBody 55 public Map<String,Object> hystrix(){ 56 return restTemplate.getForObject(SERVER_IP_PORT+"/student/hystrix/", Map.class); 57 } 58 59 }
然后我们来测试下
先启动三个eureka,再启动带hystrix的provider,最后启动普通的consumer;
浏览器:http://localhost/student/hystrix
返回:
因为 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配置文件加上
1 hystrix: 2 command: 3 default: 4 execution: 5 isolation: 6 thread: 7 timeoutInMilliseconds: 3000
改成3秒 然后 我们代码里sleep修改成2秒测试;
测试OK
sleep修改成4秒;
Hystrix服务监控Dashboard
Hystrix服务监控Dashboard仪表盘
Hystrix提供了 准实时的服务调用监控项目Dashboard,能够实时记录通过Hystrix发起的请求执行情况,
可以通过图表的形式展现给用户看。
我们新建项目:microservice-student-consumer-hystrix-dashboard-90
加依赖:
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.yuan</groupId> 7 <artifactId>t226microservice</artifactId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 11 <artifactId>microservice-student-consumer-hystrix-dashboard-90</artifactId> 12 13 <properties> 14 <java.version>1.8</java.version> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>org.springframework.boot</groupId> 20 <artifactId>spring-boot-starter</artifactId> 21 </dependency> 22 23 <dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-test</artifactId> 26 <scope>test</scope> 27 <exclusions> 28 <exclusion> 29 <groupId>org.junit.vintage</groupId> 30 <artifactId>junit-vintage-engine</artifactId> 31 </exclusion> 32 </exclusions> 33 </dependency> 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.yuan.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 }
这样就完事了。
我们启动这个项目;
然后浏览器输入:http://localhost:90/hystrix
出现这个 就说明OK;
然后我们来测试下;
我们启动三个eureka,然后再启动microservice-student-provider-hystrix-1004
我们直接请求http://localhost:1004/student/hystrix
返回正常业务
指标含义:
各种情况:
谢谢观看!!!