问题引入
-
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败!
-
服务雪崩
服务雪崩产生于服务堆积在同一个线程池中,因为所有的请求都是同一个线程池进行处理,这时候如果在高并发情况下,所有的请求全部访问同一个接口,这时候可能会导致其他服务没有线程进行接受请求,这就是服务雪崩。
hystrix是什么
-
Hystrix的中文含义是豪猪, 因其背上长满了刺,而拥有自我保护能力。 Hystrix 是一个通过增加延迟容错和容错逻辑来控制分布式服务之间交互的一个库。Hystrix通过线程隔离,防止错误级联传递,导致服务雪崩,从而提高服务稳定性
-
Hystrix设计原则:
- 防止单个依赖耗尽了服务容器的用户线程
- 降低负载以及快速失败,而不是排队
- 当可以阻止服务的失败时提供回退策略
- 使用隔离技术减少任意依赖的影响
- 通过近实时指标、监控和告警优化发现时间
- 在Hystrix的大多数方面,通过配置更改的低延迟和对动态属性更改的支持,使得可以在低延迟的情况下进行实时修改操作,从而优化恢复时间
- 防止整个依赖关系客户端执行中的故障,而不仅仅是网络流量
- Hystrix的主要目标:
- 通过隔离第三方客户端库访问依赖关系,防止和控制延迟和故障;
- 防止复杂分布式系统的级联失败;
- 快速响应失败并迅速恢复;
- 提供回滚以及友好降级;
- 实现近实时监控,告警和操作控制
服务熔断
- 熔断机制是应对雪崩效应的一种微服务链路保护机制。
- 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路,在SpringCloud框架机制通过Hystrix实现,Hystrix会监控微服务见调用的状况,当失败的调用到一个阈值,缺省是5秒内20次调用失败就会启动熔断机制,熔断机制的注解是@HystrixCommand
- 下图演示服务熔断
服务熔断(服务提供者中配置)
- 导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
- 更改配置
#Eureka的配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept-hystrix-8001 # 修改eureka上的默认描述信息
- 在熔断的方法上指定解决方案
import com.kuang.springcloud.pojo.Dept;
import com.kuang.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
//提供Restful服务!
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if (dept==null){
throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
}
return dept;
}
//备选方法
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
.setDb_source("no this database in MySQL");
}
}
- 启动类开启断路器的支持
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中!
@EnableDiscoveryClient //服务发现~
@EnableCircuitBreaker //添加对熔断的支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class,args);
}
}
服务降级(客户端配置)
- APIservice层添加一个类
import com.kuang.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
//降级 ~
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭")
.setDb_source("没有数据~");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
- feign模块添加配置
feign:
hystrix:
enabled: true
服务熔断与服务降级对比
- 服务熔断:服务端、某个服务超时或异常,引起熔断、保险丝
- 服务降级:客户端、从整体网站请求负载考虑、当某个服务熔断或关闭后,服务将不再调用,此时客户端可准备自己的失败回调返回一个缺省值。整体服务水平下降。但可以用,比直接挂掉强。
Dashboard流监控(客户端配置)
- 导入hystrix及hystrix-dashboard依赖
<!--Hystrix依赖~-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
- 编写配置文件
server:
port: 9001
- 启动类开启注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard //开启
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class,args);
}
}
- 服务端启动类需要添加监控配置并注入监控dashboard的bean(服务端也要导依赖);Controller中添加注解
<!--actuator完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中!
@EnableDiscoveryClient //服务发现~
@EnableCircuitBreaker //
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
//增加一个 Servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
//提供Restful服务!
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if (dept==null){
throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
}
return dept;
}
//备选方法
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
.setDb_source("no this database in MySQL");
}
}
- 登录查看状态
进入locahost:9001/hystrix
输入监控地址:localhost:8001/actuator/hystrix.stream