为什么会被卡死?
tomcat的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。
POM文件:
<!--新增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>
服务降级:
package com.atguigu.springcloud.service; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class PaymentService { //成功 public String paymentInfo_OK(Integer id){ return "线程池:"+Thread.currentThread().getName()+" paymentInfo_OK,id: "+id+" "+"哈哈哈" ; } //失败 @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") //3秒钟以内就是正常的业务逻辑 }) public String paymentInfo_TimeOut(Integer id){ // int timeNumber = 5; int age = 10/0; // try { TimeUnit.SECONDS.sleep(timeNumber); }catch (Exception e) {e.printStackTrace();} //return "线程池:"+Thread.currentThread().getName()+" paymentInfo_TimeOut,id: "+id+" "+"呜呜呜"+" 耗时(秒)"+timeNumber; return "线程池:"+Thread.currentThread().getName()+" paymentInfo_TimeOut,id: "+id+" "+"呜呜呜"+" 耗时(秒)"; } //兜底方法 public String paymentInfo_TimeOutHandler(Integer id){ return "线程池:"+Thread.currentThread().getName()+" 系统繁忙或者运行时异常, 请稍候再试 ,id: "+id+" "+"哭了哇呜"; } }
Hystrix的服务降级可以在客户端也可以在服务端,但是一般放在客户端,即消费者。但是,我们自己配置过的热部署方式对java代码的改动明显,但对@HystrixCommand内属性的修改建议重 启微服务
做不同的服务降级的yml:
代码膨胀: 每个业务方法对应一个兜底的方法,代码膨胀,且每个兜底方法和业务方法混在一起。
即有配置@HystrixCommand的就用特指的,否则用@DefaultPropertie通用的
package com.atguigu.springcloud.controller; import com.atguigu.springcloud.service.PaymentHystrixService; import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @Slf4j @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") //全局的 public class OrderHystrixController { @Resource private PaymentHystrixService paymentHystrixService; @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id){ String result = paymentHystrixService.paymentInfo_OK(id); return result; } // @GetMapping("/consumer/payment/hystrix/timeout/{id}") // public String paymentInfo_TimeOut(@PathVariable("id") Integer id){ // String result = paymentHystrixService.paymentInfo_TimeOut(id); // return result; // } @GetMapping("/consumer/payment/hystrix/timeout/{id}") // @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = { // @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") //1.5秒钟以内就是正常的业务逻辑 // }) @HystrixCommand public String paymentInfo_TimeOut(@PathVariable("id") Integer id){ int age = 10/0; String result = paymentHystrixService.paymentInfo_TimeOut(id); return result; } //兜底方法 public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){ return "我是消费者80,对付支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,(┬_┬)"; } //下面是全局fallback方法 public String payment_Global_FallbackMethod(){ return "Global异常处理信息,请稍后再试,(┬_┬)"; } }
代码混乱
代码混乱的解决:
cotroller:
package com.atguigu.springcloud.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * @author wsk * @date 2020/3/14 10:21 */ @Component @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" ,fallback = PaymentFallbackService.class) public interface PaymentHystrixService { @GetMapping("/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id); @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_TimeOut(@PathVariable("id") Integer id); }
实现接口:
package com.atguigu.springcloud.service; import org.springframework.stereotype.Component; @Component public class PaymentFallbackService implements PaymentHystrixService { @Override public String paymentInfo_OK(Integer id) { return "-----PaymentFallbackService fall back-paymentInfo_OK , (┬_┬)"; } @Override public String paymentInfo_TimeOut(Integer id) { return "-----PaymentFallbackService fall back-paymentInfo_TimeOut , (┬_┬)"; } }
yml:
server: port: 80 eureka: client: fetch-registry: false service-url: defaultZone: http://eureka7001.com:7001/eureka/ feign: hystrix: enabled: true
主启动类:
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.openfeign.EnableFeignClients; /** * @author wsk * @date 2020/3/14 10:09 */ @SpringBootApplication @EnableFeignClients @EnableHystrix public class OrderHystrixMain80 { public static void main(String[] args) { SpringApplication.run(OrderHystrixMain80.class,args); } }
二:服务熔断
cotroller:
//服务熔断 @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()+" "+"调用成功,流水号:"+serialNumber; }
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){ return "id 不能负数,请稍候再试,(┬_┬)/~~ id: " +id; }
断路器在什么情况下开始起作用?
断路器开启或者关闭的条件:
断路器打开之后:
open------- half open ---- close
结论:
1:先熔断,在服务降级
2 多次错误然后慢慢正确,发现刚开始不满足条件,就算是正确的访问地址也不能进行访问,需要慢慢的恢复链路,
服务监控hystrixDashboard:
actuator监控信 息完善
注意:新版本Hystrix需要在主启动类MainAppHystrix8001中指定监控路径
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class,args);
}
//springcloud升级后要加入否则会被报错
@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; }
}