构建cloud-provider-hystrix-payment8001
pom
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>cloud2020</artifactId><groupId>com.carve.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-provider-hystrix-payment8001</artifactId><dependencies><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>com.carve.springcloud</groupId><artifactId>cloud-api-common</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></project>
yml
server:port: 8001spring:application:name: cloud-provider-hystrix-paymenteureka:client:register-with-eureka: truefetch-registry: trueservice-url:defaultZone: http://eureka7001.com:7001/eureka# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
启动类
@SpringBootApplication@EnableEurekaClientpublic class PaymentHystrixMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentHystrixMain8001.class, args);}}
service
@Servicepublic class PaymentService {// 正常访问public String paymentInfo_OK(Integer id) {return "线程池:" + Thread.currentThread().getName() + " paymentInfo_OK(),id:" + id;}// 超时访问public String paymentInfo_TimeOut(Integer id) {int timeNumber = 3;try {TimeUnit.SECONDS.sleep(timeNumber);} catch (InterruptedException e) {e.printStackTrace();}return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut(),id:" + id + " 耗时(秒)" + timeNumber;}}
controller
@RestController@Slf4jpublic class PaymentController {@Resourceprivate PaymentService paymentService;// 正常访问@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id) {String result = paymentService.paymentInfo_OK(id);log.info("*****result:" + result);return result;}// 超时访问@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {String result = paymentService.paymentInfo_TimeOut(id);log.info("*****result:" + result);return result;}}
正常测试
启动eureka7001
启动eureka-provider-hystrix-payment8001
访问 http://localhost:8001/payment/hystrix/ok/31
访问 http://localhost:8001/payment/hystrix/timeout/31 每次调用耗时3秒
接下来,以上述为根基平台,从正确->错误->降级熔断->恢复
高并发测试
Jmeter压测测试
https://jmeter.apache.org/download_jmeter.cgi
开启Jmeter,来2w个并发压死8001, 2w个请求都去访问paymentInfo_TimeOut服务
然后访问 http://localhost:8001/payment/hystrix/timeout/31
Jmeter压测结论
卡死原因: tomcat的默认工作线程数被打满了,没有多余的线程来分解压力和处理
上面还只是服务提供者8001自己测试,假如此时外部的消费者80也来访问,那消费者只能干等,最终导致消费端80不满意,服务端8001直接被拖死
加入cloud-consumer-feign-hystrix-order80
pom
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>cloud2020</artifactId><groupId>com.carve.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-feign-hystrix-order80</artifactId><dependencies><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>com.carve.springcloud</groupId><artifactId>cloud-api-common</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></project>
yml
server:port: 80eureka:client:register-with-eureka: falsefetch-registry: trueservice-url:defaultZone: http://eureka7001.com:7001/eureka# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderHystrixMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderHystrixMain80.class, args);
}
}
service
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService {
// 正常访问
@GetMapping("/payment/hystrix/ok/{id}")
String paymentInfo_OK(@PathVariable("id") Integer id);
// 超时访问
@GetMapping("/payment/hystrix/timeout/{id}")
String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}
controller
@RestController
@Slf4j
public class OrderHyrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
// 正常访问
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id) {
String result = paymentHystrixService.paymentInfo_OK(id);
log.info("*****result:" + result);
return result;
}
// 超时访问
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
String result = paymentHystrixService.paymentInfo_TimeOut(id);
log.info("*****result:" + result);
return result;
}
}
测试
正常访问 http://localhost/consumer/payment/hystrix/ok/32
开启Jmeter,来2w个并发压死8001
http://localhost/consumer/payment/hystrix/ok/32
消费者80, 要么转圈圈, 要么消费端报超时错误
如何解决?解决的要求
超时导致服务器变慢(转圈) -> 超时不再等待
出错(宕机或程序运行出错) -> 出错要有兜底
解决
- 对方服务(8001)超时了,调用者(80)不能一直卡死等待,必须有服务降级
- 对方服务(8001)down机了,调用者(80)不能一直卡死等待,必须有服务降级
- 对方服务(8001)ok,调用者(80)自己有故障或有自我要求(自己的等待时间小于服务提供者)
