从浅入深 学习 SpringCloud 微服务架构(七)Hystrix(1)
一、Hystrix:基于 RestTemplate 的熔断配置
1、Hystrix 介绍:
1)Hystrix 是由 Netflix 开源的一个延迟和容错库,
用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
2)Hystrix 主要通过以下几点实现延迟和容错。
包裹请求:
使用HystrixCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。
这使用了设计模式中的“命令模式”。
跳闸机制:
当某服务的错误率超过一定的阈值时,Hystrix可以自动或手动跳闸,停止请求该服务一段时间。
资源隔离:
Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。
如果该线程池已满发往该依赖的请求就被立即拒绝,而不是排队等待,从而加速失败判定。
监控:
Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
回退机制:
当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。
回退逻辑由开发人员截图(Alt + A)自行提供,例如返回一个缺省值。
自我修复:
断路器打开一段时间后,会自动进入“半开“状态。
2、Hystrix 组件 对 RestTemplate 的支持,分4步:
1)引入 hystrix 的依赖。
2)在启动类中激活 hystrix
3)配置熔断触发的降级逻辑。
4)在需要收到保护的接口上使用 @HystrixCommand 配置。
二、Hystrix:基于 RestTemplate 的熔断配置,Hystrix 组件 对 RestTemplate 的支持,搭建案例:准备工作–创建 mysql 数据库,数据表,插入测试数据。
1、准备 mysql 数据库表。
— 创建数据库:
create database shop;
— 使用数据库:
use shop;
— 创建数据表:
CREATE TABLE `tb_product` (
`id` int NOT NULL AUTO_INCREMENT,
`product_name` varchar(40) DEFAULT NULL COMMENT '名称',
`status` int DEFAULT NULL COMMENT '状态',
`price` decimal(10,2) DEFAULT NULL COMMENT '单价',
`product_desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '描述',
`caption` varchar(255) DEFAULT NULL COMMENT '标题',
`inventory` int DEFAULT NULL COMMENT '库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3
2、向 mysql 数据表中插入数据:
insert into `tb_product` (`id`, `product_name`, `status`, `price`, `product_desc`, `caption`, `inventory`) values('1','iPhone 15 Pro','1','7999.00','iPhone 15 Pro 6.7 英寸或 6.1 英寸, 超视网膜 XDR 显示屏,ProMotion 自适应刷新率技术,钛金属搭配亚光质感玻璃背板, 灵动岛功能, A17 Pro 芯片,配备 6 核图形处理器, Pro 级摄像头系统,主摄 4800 万像素 | 超广角 | 长焦, 10 倍, 支持 USB 3, 视频播放最长可达 29 小时。 ','iPhone 15 Pro 巅峰之作','99');
三、Hystrix:基于 RestTemplate 的熔断配置,Hystrix 组件 对 RestTemplate 的支持,搭建案例:创建 Maven 父工程,导入相关依赖坐标。
1、打开 idea 创建父工程
创建 artifactId 名为 spring_cloud_consul_demo 的 maven 工程。
--> idea --> File
--> New --> Project
--> Maven
Project SDK: ( 1.8(java version "1.8.0_131" )
--> Next
--> Groupld : ( djh.it )
Artifactld : ( spring_cloud_consul_demo )
Version : 1.0-SNAPSHOT
--> Name: ( spring_cloud_consul_demo )
Location: ( D:\java_test\Intesij_idea\spring_cloud_consul_demo )
--> Finish
2、在父工程 spring_cloud_consul_demo 的 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">
<modelVersion>4.0.0</modelVersion>
<groupId>djh.it</groupId>
<artifactId>spring_cloud_consul_demo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>product_service</module>
<module>order_service</module>
<module>eureka_service</module>
<module>import_eurekaserver_test</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<!-- spring_cloud_consul_demo\pom.xml -->
3、由于父工程中,我们不准备写代码,所以可以删除 src 目录。
四、Hystrix:基于 RestTemplate 的熔断配置,Hystrix 组件 对 RestTemplate 的支持,搭建案例:在父工程 spring_cloud_consul_demo 下,创建子工程 eureka_service(子模块)。搭建 EurekaServer 注册中心。
1、搭建 EurekaServer 注册中心,使用 Eureka 的步骤:
1)搭建 EurekaServer, 创建工程,导入依赖坐标,配置 application.yml 文件,配置启动类。
2)将服务提供者注册到 EurekaServer
3)服务消费者通过注册中心获取服务列表,并调用。
2、在父工程 spring_cloud_consul_demo 下,创建子工程(子模块)eureka_service
--> 右键 spring_cloud_demo 父工程
--> Modules
--> Maven
--> Groupld : ( djh.it )
Artifactld : ( eureka_service )
Version : 1.0-SNAPSHOT
--> Next
--> Module name: ( eureka_service )
Content root : ( spring_cloud_demo\eureka_service )
Module file location: ( spring_cloud_demo\eureka_service )
--> Finish
3、在注册中心子工程 eureka_service 的 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>spring_cloud_consul_demo</artifactId>
<groupId>djh.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka_service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
<!-- spring_cloud_sonsul_demo\eureka_service\pom.xml -->
4、在注册中心子工程 eureka_service 子模块中,创建配置文件 application.yml
## spring_cloud_sonsul_demo\eureka_service\src\main\resources\application.yml
# 如果演示 eureka 高可用,可以模拟两个 EurekaServer, 一个端口 9000,一个端口 8000,两个需要相互注册。
server:
port: 9000 # 启动端口 命令行注入。
spring:
application:
name: service-eureka #spring应用名, # 注意 FeignClient 不支持名字带下划线
eureka: # 配置 eureka_server
# instance:
# hostname: localhost
client:
register-with-eureka: false # 是否将自己注册到注册中心,不配置时,默认 true。 配置高可用时,须注销此行,或配置为 true
fetch-registry: false # 是否从 Eureka 中获取注册信息,不配置时,默认 true。 配置高可用时,须注销此行,或配置为 true
service-url: # 配置暴露给 EurekaClient 的请求地址
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://127.0.0.1:9000/eureka/ # 配置高可用时,须配置为另一个 EurekaServerApplication 的端口号,如:8000
server:
enable-self-preservation: false # 关闭自我保护机制
eviction-interval-timer-in-ms: 4000 # 设置剔除服务间隔时间为 4000 毫秒(4秒)。此参数默认为 true。
5、在注册中心子工程 eureka_service 子模块中,创建 启动类 EurekaServerApplication.java
/**
* spring_cloud_sonsul_demo\eureka_service\src\main\java\djh\it\eureka\EurekaServerApplication.java
*
* 2024-4-27 eureka 注册中心,启动类 EurekaServerApplication.java
*/
package djh.it.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
6、在注册中心子工程 eureka_service 子模块中,运行启动类,进行测试
浏览器地址栏输入:http://localhost:9000 输出界面如下:
五、Hystrix:基于 RestTemplate 的熔断配置,Hystrix 组件 对 RestTemplate 的支持,
搭建案例:在父工程 spring_cloud_consul_demo 下,创建子工程 product_service(子模块)。
1、在父工程 spring_cloud_consul_demo 下,创建服务提供者 子工程(子模块)product_service。
--> 右键 spring_cloud_consul_demo 父工程
--> Modules
--> Maven
--> Groupld : ( djh.it )
Artifactld : ( product_service )
Version : 1.0-SNAPSHOT
--> Next
--> Module name: ( product_service )
Content root : ( D:\java_test\Intesij_idea\spring_cloud_consul_demo\product_service )
Module file location: ( D:\java_test\Intesij_idea\spring_cloud_consul_demo\product_service )
--> Finish
2、在服务提供者子工程 product_service 模块中的 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>spring_cloud_consul_demo</artifactId>
<groupId>djh.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product_service</artifactId>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <version>5.1.32</version>-->
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 导入 eureka 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- <!– springcloud 提供的对基于 consul 的服务发现 –>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId>-->
<!-- </dependency>-->
<!-- <!– actuator 健康检查 –>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
<!-- </dependency>-->
</dependencies>
</project>
<!-- spring_cloud_consul_demo\product_service\pom.xml -->
3、在服务提供者子工程 product_service 模块中,创建 商品实体类 Product.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\domain\Product.java
*
* 2024-4-27 商品实体类 Product.java
*/
package djh.it.product.domain;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;
@Data
@Entity
@Table(name="tb_product") //对应数据库中的数据表
public class Product {
@Id
private Long id;
private String productName;
private Integer status;
private BigDecimal price;
private String productDesc;
private String caption;
private Integer inventory;
}
4、在服务提供者子工程 product_service 模块中,创建 dao 持久层接口类 ProductDao.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\dao\ProductDao.java
*
* 2024-4-27 dao 持久层接口 ProductDao.java
*/
package djh.it.product.dao;
import djh.it.product.domain.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface ProductDao
extends JpaRepository<Product, Long>, JpaSpecificationExecutor<Product> {
}
5、在服务提供者子工程 product_service 模块中,创建 service 服务层 接口类 ProductService.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\service\ProductService.java
*
* 2024-4-27 service 服务层 接口 ProductService.java
*/
package djh.it.product.service;
import djh.it.product.domain.Product;
public interface ProductService {
//根据id查询
Product findById(Long id);
//保存
void save(Product product);
//更新
void update(Product product);
//删除
void delete(Long id);
}
6、在服务提供者子工程 product_service 模块中,创建 service 服务层 实现类 ProductServiceImpl.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\service\Impl\ProductServiceImpl.java
*
* 2024-4-27 service 服务层 实现类
*/
package djh.it.product.service.Impl;
import djh.it.product.domain.Product;
import djh.it.product.dao.ProductDao;
import djh.it.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao productDao;
@Override
public Product findById(Long id) {
return productDao.findById(id).get();
}
@Override
public void save(Product product) {
productDao.save(product);
}
@Override
public void update(Product product) {
productDao.save(product);
}
@Override
public void delete(Long id) {
productDao.deleteById(id);
}
}
7、在服务提供者子工程 product_service 模块中,创建 商品的 controller 类 ProductController.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\controller\ProductController.java
*
* 2024-4-27 商品的 controller 类 ProductController.java
*/
package djh.it.product.controller;
import djh.it.product.domain.Product;
import djh.it.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
//获取服务器端口号
@Value("${server.port}")
private String port;
//获取服务器IP地址
@Value("${spring.cloud.client.ip-address}") //springcloud 自动获取当前应用的IP地址
private String ip;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id){
try {
Thread.sleep(2000l); //延迟2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
Product product = productService.findById(id);
product.setProductName("访问的服务地址:"+ip+":"+port);
return product;
}
@RequestMapping(value = "", method = RequestMethod.POST)
public String save (@RequestBody Product product){
productService.save(product);
return "保存成功";
}
}
8、在服务提供者子工程 product_service 模块中,创建配置文件 application.yml
## spring_cloud_consul_demo\product_service\src\main\resources\application.yml
server:
port: 9001 # 启动端口 命令行注入。
# port: ${port:9001} # 启动端口设置为动态传参,如果未传参数,默认端口为 9001
spring:
application:
name: service-product #spring应用名, # 注意 FeignClient 不支持名字带下划线
# main:
# allow-bean-definition-overriding: true # SpringBoot2.1 需要设定。
datasource:
driver-class-name: com.mysql.jdbc.Driver # mysql 驱动
# url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8
url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 12311
jpa:
database: MySQL
show-sql: true
open-in-view: true
eureka: # 配置 Eureka
client:
service-url:
defaultZone: http://localhost:9000/eureka/ # 多个 eurekaserver 用 , 隔开。
instance:
prefer-ip-address: true # 使用 ip 地址注册
# # 配置 consul 的服务注册
# cloud:
# consul:
# host: 127.0.0.1 # consul 服务器的主机地址
# port: 8500 # consul 端口
# discovery:
# register: true # 是否需要注册,默认是 false
# instance-id: ${spring.application.name}-1 # 注册的实例 ID(唯一标志)
# service-name: ${spring.application.name} # 服务的名称
# port: ${server.port} # 服务的请求端口
# prefer-ip-address: true # 指定开启 IP 地址注册
# ip-address: ${spring.cloud.client.ip-address} # 当前服务的请求 IP
9、在服务提供者子工程 product_service 模块中,创建 启动类 ProductApplication.java
/**
* spring_cloud_consul_demo\product_service\src\main\java\djh\it\product\ProductApplication.java
*
* 2024-4-27 启动类 ProductApplication.java
*/
package djh.it.product;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EntityScan("djh.it.product.domain")
@EnableEurekaClient //激活 EurekaClient 同 @EnableDiscoveryClient 注解
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
10、在服务提供者子工程 product_service 模块中,运行启动类,进行测试
浏览器地址栏输入:http://localhost:9000
发现多了 service-product 服务,端口号为 9001.
浏览器地址栏输入:http://localhost:9001/product/1
输出一条 mysql 数据。
六、Hystrix:基于 RestTemplate 的熔断配置,Hystrix 组件 对 RestTemplate 的支持,搭建案例:在父工程 spring_cloud_consul_demo 下,创建子工程 order_service(子模块)。
1、在父工程 spring_cloud_consul_demo 下,创建 服务消费者 子工程(子模块)order_service
--> 右键 spring_cloud_consul_demo 父工程
--> Modules
--> Maven
--> Groupld : ( djh.it )
Artifactld : ( order_service )
Version : 1.0-SNAPSHOT
--> Next
--> Module name: ( order_service )
Content root : ( spring_cloud_consul_demo\order_service )
Module file location: ( spring_cloud_consul_demo\order_service )
--> Finish
2、在服务消费者 order_service 子工程(子模块) 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>spring_cloud_consul_demo</artifactId>
<groupId>djh.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order_service</artifactId>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <version>5.1.32</version>-->
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 导入 eureka 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- springcloud 提供的对基于 consul 的服务发现 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId>-->
<!-- </dependency>-->
<!-- <!– actuator 健康检查 –>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
<!-- </dependency>-->
<!-- springcloud 整合 openFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Hystrix 组件 对 RestTemplate 的支持4步:1)引入 Hystrix 依赖坐标 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
</project>
<!-- spring_cloud_consul_demo\order_service\pom.xml -->
3、在服务消费者 order_service 子工程(子模块)中,创建配置文件 application.yml
## spring_cloud_consul_demo\order_service\src\main\resources\application.yml
server:
port: 9002 # 启动端口 命令行注入。
# port: ${port:9002} # 启动端口设置为动态传参,如果未传参数,默认端口为 9002
spring:
application:
name: service-order #spring应用名, # 注意 FeignClient 不支持名字带下划线
# main:
# allow-bean-definition-overriding: true # SpringBoot2.1 需要设定。
datasource:
driver-class-name: com.mysql.jdbc.Driver # mysql 驱动
# url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8
url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 12311
jpa:
database: MySQL
show-sql: true
open-in-view: true
eureka: # 配置 Eureka
client:
service-url:
defaultZone: http://localhost:9000/eureka/ # 多个 eurekaserver 用 , 隔开。
instance:
prefer-ip-address: true # 使用 ip 地址注册
hystrix: # 配置 hystrix 熔断
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 默认的连接超时时间为1秒,若1秒没有返回数据,会自动触发降级逻辑。
# # 配置 consul 的服务注册
# cloud:
# consul:
# host: 127.0.0.1 # consul 服务器的主机地址
# port: 8500 # consul 端口
# discovery:
# register: false # 是否需要注册,默认是 false
# instance-id: ${spring.application.name}-1 # 注册的实例 ID(唯一标志)
# service-name: ${spring.application.name} # 服务的名称
# port: ${server.port} # 服务的请求端口
# prefer-ip-address: true # 指定开启 IP 地址注册
# ip-address: ${spring.cloud.client.ip-address} # 当前服务的请求 IP
4、在服务消费者 order_service 子工程(子模块)中,创建 商品实体类 Product.java
/**
* spring_cloud_demo\order_service\src\main\java\djh\it\order\domain\Product.java
*
* 2024-4-27 商品实体类 Product.java
*/
package djh.it.order.domain;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class Product {
private Long id;
private String productName;
private Integer status;
private BigDecimal price;
private String productDesc;
private String caption;
private Integer inventory;
}
5、在服务消费者 order_service 子工程(子模块)中,创建 controller 类 OrderController.java
/**
* spring_cloud_consul_demo\order_service\src\main\java\djh\it\order\controller\OrderController.java
*
* 2024-4-27 订单的 controller 类 OrderController.java
*/
package djh.it.order.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import djh.it.order.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired // 注入 restTemplate 对象
private RestTemplate restTemplate;
/**
* Hystrix 组件 对 RestTemplate 的支持4步:4)使用注解配置熔断保护
* fallbackmethod : 配置熔断之后的降级方法
* @param id
* @return
*/
@HystrixCommand(fallbackMethod = "orderFallBack")
@RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id){
Product product = null;
//product = restTemplate.getForObject("http://127.0.0.1:9001/product/1", Product.class);
product = restTemplate.getForObject("http://service-product/product/1", Product.class);
return product;
}
/**
* Hystrix 组件 对 RestTemplate 的支持4步:3)降级方法
* 例如:如果访问的 service-product 服务器宕机,就会触发此降级方法
* @param id
* @return
*/
public Product orderFallBack(Long id){
Product product = new Product();
product.setProductName("触发降级方法");
return product;
}
}
6、在服务消费者 order_service 子工程(子模块)中,创建 启动类 OrderApplication.java
/**
* spring_cloud_demo\order_service\src\main\java\djh\it\order\OrderApplication.java
*
* 2024-4-27 启动类 OrderApplication.java
*/
package djh.it.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EntityScan("djh.it.order.domain")
@EnableEurekaClient //激活 EurekaClient,同 @EnableDiscoveryClient 注解相同。
//@EnableFeignClients //激活 Feign
@EnableCircuitBreaker // Hystrix 组件 对 RestTemplate 的支持4步:2)激活 hystrix
public class OrderApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
7、在服务消费者 order_service 子工程(子模块)中,运行启动类,product_service 模块中,运行启动类,eureka_service 模块中,运行启动类,进行测试
1)浏览器地址栏输入:http://127.0.0.1:9000
发现 两个 服务,点击 此服务,端口号分别是 9001.9002。
2)浏览器地址栏输入:http://127.0.0.1:9001/product/1
正常输出 mysql 数据库的第一条记录:
3)浏览器地址栏输入:http://127.0.0.1:9002/order/buy/1
正常输出 mysql 数据库的第一条记录。
4)例如:如果访问的 service-product 服务器宕机,service-order 模块中,就会触发此降级方法。
把 服务提供者 product_service 模块中,启动类停止,再次访问测试,发现触发了降级方法。
浏览器地址栏输入:http://127.0.0.1:9002/order/buy/1
上一节链掊请点击:
# 从浅入深 学习 SpringCloud 微服务架构(六)Feign(3)