提交 2200a977 编写于 作者: Lcry's avatar Lcry 🖥

P47-P64:完成服务降级和服务熔断Hystrix,更新Readme

上级 61ec0acf
......@@ -119,3 +119,9 @@ cloud-provider-consul-payment8006/target/
cloud-provider-consul-payment8006/src/test/
cloud-consumer-feign-order80/target/
cloud-consumer-feign-order80/src/test/
cloud-provider-hystrix-payment8001/src/test
cloud-provider-hystrix-payment8001/target/
cloud-consumer-feign-hystrix-order80/src/test/
cloud-consumer-feign-hystrix-order80/target/
cloud-consumer-hystrix-dashboard9001/src/test/
cloud-consumer-hystrix-dashboard9001/target/
\ No newline at end of file
......@@ -14,19 +14,23 @@ Maven:3.5及以上
MySQL:5.7及以上
#### 项目结构
| 项目名 | 用途 | 所用技术 |
| --------------------------------- | :--------------------------------- | ----------------------------------------------- |
| cloud-api-commons | 公共代码部分(返回结果集、实体等) | \ |
| cloud-consumer-consul-order80 | 消费方通过Consul调用服务方 | 注册中心(Consul)、远程调用(RestTemplate) |
| cloud-consumer-feign-order80 | 消费方通过feign远程调用服务方 | 服务调用(openfeign)、注册中心(EurekaClient) |
| cloud-consumer-order80 | 消费方通过Eureka调用服务方等示例 | 注册中心(Eureka)、远程调用(RestTemplate) |
| cloud-consumer-zk-order80 | 消费方通过Zk调用服务方 | 注册中心(Zk)、远程调用(RestTemplate) |
| cloud-eureka-server7001 | Eureka服务端1 | 注册中心(EurekaServer) |
| cloud-eureka-server7002 | Eureka服务端2 | 注册中心(EurekaServer) |
| cloud-provider-consul-payment8006 | 服务方通过Consul注册服务 | 注册中心(Consul) |
| cloud-provider-payment8001 | 服务方通过Eureka注册服务 | 注册中心(Euraka) |
| cloud-provider-payment8002 | 服务方通过Eureka注册服务 | 注册中心(Euraka) |
| cloud-provider-zk-payment8004 | 服务方通过Zk注册服务 | 注册中心(Zk) |
| 项目名 | 用途 | 所用技术 |
| ------------------------------------ | :---------------------------------------------- | ------------------------------------------------ |
| cloud-api-commons | 公共代码部分(返回结果集、实体等) | \ |
| cloud-consumer-consul-order80 | 消费方通过Consul调用服务方 | 注册中心(Consul)、远程调用(RestTemplate) |
| cloud-consumer-feign-order80 | 消费方通过feign远程调用服务方 | 服务调用(Openfeign)、注册中心(EurekaClient) |
| cloud-consumer-order80 | 消费方通过Eureka调用服务方等示例 | 注册中心(Eureka)、远程调用(RestTemplate) |
| cloud-consumer-zk-order80 | 消费方通过Zk调用服务方 | 注册中心(Zk)、远程调用(RestTemplate) |
| cloud-eureka-server7001 | Eureka服务端1 | 注册中心(EurekaServer) |
| cloud-eureka-server7002 | Eureka服务端2 | 注册中心(EurekaServer) |
| cloud-provider-consul-payment8006 | 服务方通过Consul注册服务 | 注册中心(Consul) |
| cloud-provider-payment8001 | 服务方通过Eureka注册服务 | 注册中心(Euraka) |
| cloud-provider-payment8002 | 服务方通过Eureka注册服务 | 注册中心(Euraka) |
| cloud-provider-zk-payment8004 | 服务方通过Zk注册服务 | 注册中心(Zk) |
| cloud-provider-hystrix-payment8001 | 服务方通过Hystrix服务降级和熔断 | 服务降级和熔断(Hystrix)、服务监控(Actuator) |
| cloud-consumer-feign-hystrix-order80 | 消费方消费方通过feign远程调用服务方带降级和服务 | 服务降级和熔断(Hystrix)、服务调用(Openfeign) |
| cloud-consumer-hystrix-dashboard9001 | Hystrix监控仪表盘 | 服务监控(Hystrix) |
......
<?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>2020SpringCloud</artifactId>
<groupId>com.lcry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 消费方feign调用+hystrix服务降级案例-->
<artifactId>cloud-consumer-feign-hystrix-order80</artifactId>
<dependencies>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--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>
<!--引入自己定义的api调用包,可以使用Payment支付Entity-->
<dependency>
<groupId>com.lcry</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</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>
<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>
\ No newline at end of file
package com.lcry.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;
/**
* 2020年3月15日 12:12:25
*/
@SpringBootApplication
@EnableFeignClients //启用OpenFeign
@EnableHystrix //客户端启用Hystrix服务降级注解
public class HystrixOrderMain80 {
public static void main(String[] args) {
SpringApplication.run(HystrixOrderMain80.class, args);
}
}
package com.lcry.springcloud.controller;
import com.lcry.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;
/**
* @auther zzyy
* @create 2020-02-20 11:57
*/
@RestController
@Slf4j
//定义全局FallbackMethod
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystirxController {
@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}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
//超时1.5s或者异常直接降级
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
//@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秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
}
// 下面是全局fallback方法
public String payment_Global_FallbackMethod() {
return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
}
}
package com.lcry.springcloud.service;
import org.springframework.stereotype.Component;
/**
* 根据Openfeign服务接口直接降级
*/
@Component
public class PaymentFallbackService implements PaymentHystrixService {
@Override
public String paymentInfo_OK(Integer id) {
return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
}
@Override
public String paymentInfo_TimeOut(Integer id) {
return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
}
}
package com.lcry.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;
/**
* Openfeign调用服务方
*/
@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);
}
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://127.0.0.1:7001/eureka/
feign:
hystrix:
enabled: true
\ No newline at end of file
<?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>2020SpringCloud</artifactId>
<groupId>com.lcry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- hystrix服务监控平台dashboard -->
<!-- 被监控服务一定要引入web和actuator两个依赖 -->
<!--
监控地址:http://ip:端口/hystrix
被监控填写:http://ip:端口/hystrix.stream
-->
<artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>
<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>
</project>
\ No newline at end of file
package com.lcry.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
/**
* HystrixDashboardMain9001
*
* @author lcry
* @date 2020/03/15 13:46
*/
@SpringBootApplication
@EnableHystrixDashboard //启用注解
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class, args);
}
}
<?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>2020SpringCloud</artifactId>
<groupId>com.lcry</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 服务熔断hystrix版实现服务方-->
<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>
<!--引入自己定义的api调用包,可以使用Payment支付Entity-->
<dependency>
<groupId>com.lcry</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>
</project>
\ No newline at end of file
package com.lcry.springcloud;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
/**
* HystrixPaymentMain8001
*
* @author lcry
* @date 2020/03/15 0:01
*/
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //服务端开启Hystrix或者使用@EnableCircuitBreaker
public class HystrixPaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentMain8001.class, args);
}
// 针对监控平台需要下面配置 监控/hystrix.stream
/**
* 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
* ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
* 只要在自己的项目里配置上下面的servlet就可以了
*/
@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;
}
}
package com.lcry.springcloud.controller;
import com.lcry.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;
/**
* PaymentController
*
* @author lcry
* @date 2020/03/15 0:06
*/
@RestController
@Slf4j
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(String.format("result:{%s}", result));
return serverPort + result;
}
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
String result = paymentService.paymentInfo_TimeOut(id);
log.info(String.format("result:{%s}", result));
return serverPort + result;
}
//服务熔断
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
String result = paymentService.paymentCircuitBreaker(id);
log.info(String.format("result:{%s}", result));
return result;
}
}
package com.lcry.springcloud.service;
import org.springframework.web.bind.annotation.PathVariable;
/**
* PaymentService
*
* @author lcry
* @date 2020/03/15 0:02
*/
public interface PaymentService {
public String paymentInfo_OK(Integer id);
public String paymentInfo_TimeOut(Integer id);
public String paymentCircuitBreaker(@PathVariable("id") Integer id);
}
package com.lcry.springcloud.service.impl;
import cn.hutool.core.util.IdUtil;
import com.lcry.springcloud.service.PaymentService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.concurrent.TimeUnit;
/**
* PaymentServiceImpl
*
* @author lcry
* @date 2020/03/15 0:03
*/
@Service
public class PaymentServiceImpl implements PaymentService {
// 服务降级
/**
* 正常访问OK
*
* @param id
* @return
*/
@Override
public String paymentInfo_OK(Integer id) {
return "线程池: " + Thread.currentThread().getName() + " paymentInfo_OK,id: " + id + "\t" + "O(∩_∩)O哈哈~";
}
/**
* 模拟超时3s
*
* @param id
* @return
*/
@Override
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
//超时5s或者异常直接降级
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
})
public String paymentInfo_TimeOut(Integer id) {
//int age = 10/0;
int timenum = 3;
try {
TimeUnit.SECONDS.sleep(timenum);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池: " + Thread.currentThread().getName() + " id: " + id + "\t" + "O(∩_∩)O哈哈~" + " 耗时(秒): " + timenum;
}
public String paymentInfo_TimeOutHandler(Integer id) {
return "线程池: " + Thread.currentThread().getName() + " 8001系统繁忙或者运行报错,请稍后再试,id: " + id + "\t" + "o(╥﹏╥)o";
}
/**
* 以下内容属于服务熔断
*
* @param id
* @return
*/
@Override
@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 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " + id;
}
}
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:7001/eureka
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
\ No newline at end of file
......@@ -19,6 +19,9 @@
<module>cloud-provider-consul-payment8006</module>
<module>cloud-consumer-consul-order80</module>
<module>cloud-consumer-feign-order80</module>
<module>cloud-provider-hystrix-payment8001</module>
<module>cloud-consumer-feign-hystrix-order80</module>
<module>cloud-consumer-hystrix-dashboard9001</module>
</modules>
<packaging>pom</packaging>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册