Hystrix
Hystrix 能解决 服务上的服务降级、服务熔断、接近实时的监控
服务降级:服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示,fallback
哪些情况会触发降级:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级
服务熔断:类比保险丝达到最大服务访问后,直接拒绝访问
服务限流:秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
一.服务降级
1.新建springcloud-provider-hystrix-payment8001 服务端
<dependencies>
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yml
server:
port: 8001
eureka:
client:
register-with-eureka: true #表识不向注册中心注册自己
fetch-registry: true #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
# defaultZone: http://eureka7002.com:7002/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka/
# server:
# enable-self-preservation: false
spring:
application:
name: cloud-provider-hystrix-payment
# eviction-interval-timer-in-ms: 2000
service
@Service
public class PaymentService {
@HystrixCommand(fallbackMethod = "paymentInfo_fallbackMethod_TimeOut",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
//3秒钟会自动执行paymentInfo_fallbackMethod_TimeOut方法,降级
})
public String paymentInfo_TimeOut(Integer id) {
int timeNumber = 2;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (Exception e) {
e.printStackTrace();
}
return " 耗时(秒)" + timeNumber;
}
public String paymentInfo_fallbackMethod_TimeOut(Integer id) {
return "8001系统错误";
}
}
controller
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@GetMapping(value = "/payment/hystrix/timeOut/{id}")
public String paymentInfo_TimeOut(@PathVariable("id")Integer id) {
return paymentService.paymentInfo_TimeOut(id);
}
}
启动类
@EnableCircuitBreaker // 开启HystrixCommand 注解
2.新建springcloud-order-feign-hystrix80
pom
<dependencies>
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.psf.springcloud</groupId>
<artifactId>springcloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yml
server:
port: 80
spring:
application:
name: cloud-feign-hystrix-order
eureka:
client:
register-with-eureka: true #禁止自己当做服务注册
fetch-registry: true #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
feign:
hystrix:
enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。打开feign对hystrix的支持 feignClient 接口中的 fallback
接口service
@Component
这是上一篇openFeign 接口
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface OrderFeignHystrixService {
@GetMapping(value = "/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) ;
@GetMapping(value = "/payment/hystrix/timeOut/{id}")
public String paymentInfo_TimeOut(@PathVariable("id")Integer id) ;
}
统一为接口做异常处理service
@Component
@FeignClient(value ="CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentfallbackService.class) //使用fallback的前提,在yml进行配置feign: hystrix: enabled:true
public interface PaymentService {
@GetMapping(value = "/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) ;
@GetMapping(value = "/payment/hystrix/timeOut/{id}")
public String paymentInfo_TimeOut(@PathVariable("id")Integer id) ;
}
PaymentfallbackService 实现类
@Component
public class PaymentfallbackService implements PaymentService {
@Override
public String paymentInfo_OK(Integer id) {
return "paymentInfo_OK fail....";
}
@Override
public String paymentInfo_TimeOut(Integer id) {
return "paymentInfo_TimeOut fail....";
}
}
专属降级controller
@RestController
@Slf4j
public class OrderFeignHystrixController {
@Resource
private OrderFeignHystrixService orderFeignHystrixService;
//客户端也为了防止在高并发情况下,等待 也添加了降级处理
@GetMapping(value = "/order/payment/timeOut/{id}")
@HystrixCommand(fallbackMethod = "paymentInfoFallbackMethodNo",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000")
})
public String paymentInfo_No(@PathVariable("id") Integer id) {
String result=orderFeignHystrixService.paymentInfo_TimeOut(id);
return "80:"+result;
}
public String paymentInfoFallbackMethodNo(@PathVariable("id") Integer id) {
return "80:系统异常,请重试"+id;
}
不用每个方法都配置上述的服务降级,下方是配置默认降级的,业务专属的降级用上方
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "paymentInfoFallbackMethodNoGlobal") //超时 异常 走全局 全局降级
public class OrderFeignHystrixController {
@Resource
private PaymentService paymentService;
@GetMapping(value = "/order/payment/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) {
String result=paymentService.paymentInfo_OK(id);
return "80:"+result;
}
@GetMapping(value = "/order/payment/timeOut/{id}")
@HystrixCommand(fallbackMethod = "paymentInfoFallbackMethodNo",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") //3秒钟以内就是正常的业务逻辑
}) //指明的 降级方法
public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
String result=paymentService.paymentInfo_TimeOut(id);
return "80:"+result;
}
public String paymentInfoFallbackMethodNo(@PathVariable("id") Integer id) {
return "80:系统异常,请重试"+id;
}
@HystrixCommand //无特别指明 全局的
@GetMapping(value = "/order/payment/Global/{id}")
public String paymentInfo_NoGlobal(@PathVariable("id") Integer id) {
String result=paymentService.paymentInfo_TimeOut(id);
return "80:"+result;
}
//下面是全局fallback方法
public String paymentInfoFallbackMethodNoGlobal(){
return "Global异常处理信息,请稍后再试,(┬_┬)";
}
}
启动类
@EnableHystrix //开启注解
启动顺序 eureka7001–> 8001–>80
二.服务熔断
熔断机制是应对雪崩效应的一种微服务链路保护机制,当某个链路响应时间太久,会进行服务降级,并且熔断该节点的调用,快速响应错误,若检测到该节点微服务调用响应后,恢复调用链路。
熔断机制的注解@HystrixCommand
测试熔断机制:
在springcloud-provider-hystrix-payment8001端口 service加入方法
service
//服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //时间范围
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), //失败率达到多少后跳闸
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
if (id < 0){
throw new RuntimeException("*****id 不能负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
return "id 不能负数,请稍候再试,(┬_┬)/~~ id: " +id;
}
controller
//===服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
String result = paymentService.paymentCircuitBreaker(id);
log.info("*******result:"+result);
return result;
}
在执行的时候,当故意失败次数达到给的默认值后,服务将熔断,如果突然正确,服务也有可能显示错误,服务自动恢复,逐渐恢复的效果
三 图形化Dashboard
1.新建moudle springcloud-hystrix-dashboard9001
pom
<dependencies>
<!--新增hystrix dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yml
server:
port: 9001
启动类
@SpringBootApplication
@EnableHystrixDashboard /开启服务监控
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class,args);
}
}
监控要求,只要是对服务端 如8001,8002等需要监控必须添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
启动9001 网页输入http://localhost:9001/hystrix
运行成功
输入 http://localhost:8001/hystrix.stream 开始进行监控
如果出现 Unable to connect to Command Metric Stream
在新版本中 被监控端需要添加
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker // 开启HystrixCommand 注解
public class HystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixMain8001.class,args);
}
//需要添加的
@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;
}
}
微服务工程构建(八)eureka环境OpenFeign使用
微服务工程构建(四) eureka集群环境构建 server与server之间相互注册配置 client修改成多个注册
代码下载
END