Hystrix 支付微服务构建
新建 cloud-provider-hystrix-payment8001
1.pom.xml
<?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>msclound</artifactId>
<groupId>com.atguigu.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>
<!--web-->
<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><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</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>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
2.application.yml
server:
port: 8003
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
defaultZone: http://eureka7001.com:7001/eureka
3.主启动类
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class PaymentHystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixMain8001.class,args);
}
}
4.业务类
(1)PaymentService
package com.atguigu.springcloud.service;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class PaymentService {
/**
* 正常访问,一切 OK
* @param id
* @return
*/
public String paymentInfo_OK(Integer id){
return "线程池:"+Thread.currentThread().getName()+"paymentInfo_OK,id:"+id+"\t"+":-)";
}
/**
* 超时访问,演示降级
* @param id
* @return
*/
public String paymentInfo_TimeOut(Integer id){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id:"+id+"\t"+":-(,耗费 3 秒";
}
}
(2)PaymentController
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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;
@Slf4j
@RestController
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@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;
}
}
测试
● 启动 cloud-eureka-server7001
● 启动 cloud-provider-hystrix-payment8001
浏览器访问:http://localhost:8003/payment/hystrix/ok/31
返回结果:
线程池:http-nio-8003-exec-1paymentInfo_OK,id:31 :-)
浏览器访问:http://localhost:8003/payment/hystrix/timeout/31
返回结果:
线程池:http-nio-8003-exec-3paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
以上述为根基平台,从正确->错误->降级熔断->恢复
JMeter 高并发压测后卡顿
上述在非高并发情形下,还能勉强满足
下面使用 Jmeter 压测测试
开启 Jmeter,来 20000 个并发压死 8001,20000 个请求都去访问 paymentInfo_TimeOut 服务
1.测试计划
中右键添加 - 线程
- 线程组
(线程组 payment2020
,线程数:200
,线程数:100
,其他参数默认)
2.刚刚新建线程组 payment2020
,右键它 - 添加 - 取样器
- Http请求
- 路径
,输入 http://localhost:8003/payment/hystrix/timeout/31
3.点击绿色三角形图标启动。
启动后,可以看到后端控制台开始疯狂打印日志
*******result:线程池:http-nio-8003-exec-33paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
*******result:线程池:http-nio-8003-exec-99paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
*******result:线程池:http-nio-8003-exec-83paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
*******result:线程池:http-nio-8003-exec-35paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
*******result:线程池:http-nio-8003-exec-81paymentInfo_TimeOut,id:31 :-(,耗费 3 秒
这个时候,浏览器输入 http://localhost:8003/payment/hystrix/ok/31
本来秒出的结果也需要几秒才出来
原因:tomcat 的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。
Jmeter 压测结论
上面还是服务提供者 8001 自己测试,假如此时外部的消费者 80 也来访问,那消费者只能干等,最终导致消费端 80 不满意,服务端 8001 直接被拖慢。