视频链接:2020最新版SpringCloud框架开发教程-周阳
文章源码:https://github.com/geyiwei-suzhou/cloud2020/
cloud-eureka-server7001模块
将Eureka服务改为单机版,修改yml配置文件
defaultZone: http://eureka7001.com:7001/eureka/
cloud-provider-hystrix-payment8001模块
1. 建module
New --> Module --> Maven[Module SDK:1.8.0_191] --> name[cloud-provider-hystrix-payment8001] --> Finish
2. 改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.antherd.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-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入公共api包-->
<dependency>
<groupId>com.antherd.springcloud</groupId>
<artifactId>cloud-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>
</project>
3. 写yml
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
register-with-eureka: true
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4. 主启动
新建类:com.antherd.springcloud.PaymentHystrixMain8001
package com.antherd.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PaymentHystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixMain8001.class, args);
}
}
新建类:com.antherd.srpingcloud.service.PaymentService
package com.antherd.springcloud.service;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
public String paymentInfoOk(Integer id) {
return "线程池:" + Thread.currentThread().getName() + " paymentInfoOk," + id + " O(∩_∩)O哈哈~";
}
public String paymentInfoTimeout(Integer id) {
int timeNumber = 3;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " paymentInfoTimeout," + id + " ┭┮﹏┭┮" + " 耗时" + timeNumber + "秒钟";
}
}
新建类:com.antherd.srpingcloud.contorller.PaymentController
package com.antherd.springcloud.controller;
import com.antherd.springcloud.service.PaymentService;
import javax.annotation.Resource;
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;
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfoOk(@PathVariable("id") Integer id) {
String result = paymentService.paymentInfoOk(id);
log.info("*****result***** : " + result);
return result;
}
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfoTimeout(@PathVariable("id") Integer id) {
String result = paymentService.paymentInfoTimeout(id);
log.info("*****result***** : " + result);
return result;
}
}
5. 启动测试
启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001两个模块
访问:http://localhost:8001/payment/hystrix/ok/1、http://localhost:8001/payment/hystrix/timeout/1 发现都可以正常访问
如果此时用jmeter对http://localhost:8001/payment/hystrix/timeout/1 进行100线程20次压测,会发现http://localhost:8001/payment/hystrix/ok/1的响应也会变慢。
ps
:Tomecat默认线程量为10。
cloud-consumer-feign-hystrix-order80模块
1. 建module
New --> Module --> Maven[Module SDK:1.8.0_191] --> name[cloud-consumer-feign-hystrix-order80] --> Finish
2. 改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.antherd.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>
<version>2.2.1.RELEASE</version>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入公共api包-->
<dependency>
<groupId>com.antherd.springcloud</groupId>
<artifactId>cloud-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>
</project>
3. 写yml
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka
4. 主启动
新建类:com.antherd.springcloud.OrderHystrixMain80
package com.antherd.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderHystrixMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderHystrixMain80.class, args);
}
}
新建类:com.antherd.srpingcloud.service.PaymentHystrixService
package com.antherd.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;
@Component
@FeignClient("CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService {
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfoOk(@PathVariable("id") Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfoTimeout(@PathVariable("id") Integer id);
}
新建类:com.antherd.srpingcloud.contorller.OrderHystrixController
package com.antherd.springcloud.controller;
import com.antherd.springcloud.service.PaymentHystrixService;
import javax.annotation.Resource;
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;
@RestController
@Slf4j
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@Value("${server.port}")
private String serverPort;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfoOk(@PathVariable("id") Integer id) {
String result = paymentHystrixService.paymentInfoOk(id);
log.info("*****result***** : " + result);
return result;
}
@GetMapping("/consumer//payment/hystrix/timeout/{id}")
public String paymentInfoTimeout(@PathVariable("id") Integer id) {
String result = paymentHystrixService.paymentInfoTimeout(id);
log.info("*****result***** : " + result);
return result;
}
}
5. 启动测试
启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001,cloud-consumer-feign-hystrix-order80三个模块
访问:http://localhost/consumer/payment/hystrix/ok/1 发现可以正常访问、http://localhost/consumer/payment/hystrix/timeout/1 发现访问超时直接显示了报错页面
解决
对方服务(8001)超时了,调用者(80)不能一直卡死等待,必须有服务降级
对方服务(8001)down机了,调用者(80)不能一直卡死等待,必须有服务降级
对方服务(8001)OK,调用者(80)自己出故障或有自我要求(自己的等待时间小于服务提供者),自己处理降级
cloud-provider-hystrix-payment8001模块
设置自身调用超时时间的峰值(3s),峰值内可以正常运行,超过了需要兜底的方法处理,作服务降级fallback
修改com.antherd.springcloud.service.PaymentService.paymentInfoTimeout方法,处理时间改为5秒,同时添加fallback注解
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
public String paymentInfoTimeout(Integer id) {
int timeNumber = 5;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " id:" + id + " O(∩_∩)O哈哈~" + " 耗时" + timeNumber + "秒钟";
}
并且编写对应的fallback方法paymentInfoTimeoutHandle
public String paymentInfoTimeoutHandle(Integer id) {
return "线程池:" + Thread.currentThread().getName() + " id:" + id + " 8001系统繁忙或运行报错,请稍后再试" + " ┭┮﹏┭┮";
}
在主启动类上添加注解激活服务降级
@EnableEurekaClient
@EnableCircuitBreaker
启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001两个模块
访问:http://localhost:8001/payment/hystrix/timeout/1 发现访问没有报错,等待3秒后执行paymentInfoTimeoutHandle方法并且返回结果
现在,我们在paymentInfoTimeout方法开始位置添加异常代码
int age = 10/0;
访问:http://localhost:8001/payment/hystrix/timeout/1 发现立刻执行paymentInfoTimeoutHandle方法并且返回结果,不会等待3秒超时
cloud-consumer-feign-hystrix-order80模块
pom文件中添加Hystrix依赖
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
修改application.yml配置,添加
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
添加@EnableHystrix注解及对@HystrixCommand内属性的修改建议重启微服务,否则可能不生效
在启动类com.antherd.springcloud.OrderHystrixMain80上加上注解
@EnableHystrix
修改类:com.antherd.springcloud.controller.OrderHystrixController
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
public String paymentInfoTimeout(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfoTimeout(id);
}
public String paymentInfoTimeoutHandle(@PathVariable("id") Integer id) {
return "我是消费者80,对方支付系统繁忙请10秒后再试或者自己运行出错请检查自己,┭┮﹏┭┮";
}
同时把8001模块com.antherd.springcloud.service.PaymentService.paymentInfoTimeout方法改为如下
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
})
public String paymentInfoTimeout(Integer id) {
// int age = 10/0;
int timeNumber = 3;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " id:" + id + " O(∩_∩)O哈哈~" + " 耗时" + timeNumber + "秒钟";
}
访问:http://localhost/consumer/payment/hystrix/timeout/1,发现消费侧启动了服务降级。然后把com.antherd.springcloud.controller.OrderHystrixController.paymentInfoTimeout 的服务降级时间改为4秒,发现可以正常访问接口。