旧版笔记:Spring colud的构建,详情跳转查看
一、创建pom项目
界面截图:

修改pom.xml引入项目依赖:
<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> <!-- 引入依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.2</version> <relativePath /> </parent> <groupId>com.namejr</groupId> <artifactId>Web_GatherCould</artifactId> <version>1.0-SNAPSHOT</version> <!-- spring cloud中,父工程使用pom --> <packaging>pom</packaging> <name>Web_GatherCould</name> <url>http://maven.apache.org</url> <modules> <module>Web_PublicCould</module> </modules> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.10.14</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- 数据库相关插件 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <!-- openapi文档 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.6.9</version> </dependency> </dependencies> <!-- 引入spring-cloud依赖,通过dependencyManagement管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.9</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2021.0.6.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
二、Nacos
1.注册中心和配置中心
创建子模块:


目录结构(无关的就不记录了):

Web_PublicCould中pom.xml配置:
<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> <parent> <groupId>com.namejr</groupId> <artifactId>Web_GatherCould</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>Web_PublicCould</artifactId> <packaging>war</packaging> <name>Web_PublicCould</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- nacos配置中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- 自2.4版本之后,默认bootstrap处于禁用状态,需要手动引入,否则会报:Add a spring.config.import=nacos: property to your configuration. --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.yml</include> <include>**/*.xml</include> <include>**/*.json</include> <include>**/*.js</include> </includes> <filtering>false</filtering> </resource> <resource> <!-- 注册webapp目录为资源目录 --> <directory>src/main/webapp</directory> <targetPath>META-INF/resources</targetPath> <includes> <include>**/**</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <includeSystemScope>true</includeSystemScope> <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> </configuration> </plugin> </plugins> </build> </project>
PublicCouldConfig.java
package com.namejr.base; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** Nacos配置中心配置内容,这是一种方式, * 另外一种是@RefreshScope,直接使用@Value("${common.configuration.adjustConfig}")获取 * */ @Component @ConfigurationProperties(prefix = "common.configuration") public class PublicCouldConfig { public String getAdjustConfig() { return adjustConfig; } public void setAdjustConfig(String adjustConfig) { this.adjustConfig = adjustConfig; } private String adjustConfig; }
PublicController.java
package com.namejr.controller; import io.swagger.v3.oas.annotations.tags.Tag; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/public") @Tag(name = "PublicController", description = "通用公共控制器") @RefreshScope public class PublicController { private static final Logger logger = LoggerFactory.getLogger(PublicController.class); @Value("${comment.configuration.testButton}") private Integer testButton; @Value("${common.configuration.adjustConfig}") private String adjustConfig; @RequestMapping(value = "/serviceTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String serviceTime() { return DateTime.now().toString("yyyy-MM-dd HH:mm:ss"); } /** 测试动态修改Nacos是否能正常获取 */ @RequestMapping(value = "/runNacosConfig", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String runNacosConfig() { return adjustConfig; } }
bootstrap.properties
# 配置Nacos服务名称(漏掉配置这个玩意可能会导致无法自动获取配置更新) spring.application.name=publicCould # Nacos配置中心服务地址 spring.cloud.nacos.config.server-addr=127.0.0.1:18848 spring.cloud.nacos.config.username=nacos spring.cloud.nacos.config.password=nacos # 指定后缀 spring.cloud.nacos.config.file-extension=properties # 动态刷新配置(新版本不再使用refresh-enable,改成下面两个) #spring.cloud.nacos.config.refresh-enable=true spring.cloud.nacos.config.enabled=true spring.cloud.nacos.config.refresh-enabled=true # 指定开发环境 spring.cloud.nacos.config.namespace=public # 指定分组 spring.cloud.nacos.config.group=DEFAULT_GROUP


application.properties
# 端口号 server.port=11101 # 配置日志 logging.config=classpath:logback-spring.xml # 版本号 comment.configuration.version=20251122 # 测试按钮 comment.configuration.testButton=1 # 配置Nacos服务名称 spring.application.name=publicCould # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:18848 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # 心跳由默认的5s改为10s spring.cloud.nacos.discovery.heart-beat-interval=10000 # 心跳由默认的15s改为20s。在20s没有收到客户端的心跳就认为客户端不不健康状态 spring.cloud.nacos.discovery.heart-beat-timeout=20000 # 如果超过60s没有收到客户端的心跳,nacos服务端变会把客户端的服务实例删除。 spring.cloud.nacos.discovery.ip-delete-timeout=60000
2.配置消费者(使用负载均衡)

pom.xml
<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> <parent> <groupId>com.namejr</groupId> <artifactId>Web_GatherCould</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>Web_Consumer</artifactId> <packaging>jar</packaging> <name>Web_Consumer</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 引入负载均衡处理 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> </project>
application.properties
# 端口号 server.port=11102 # 配置日志 logging.config=classpath:logback-spring.xml # mysql数据库配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3307/web_test?characterEncoding=UTF-8&allowMultiQueries=true&&useAffectedRows=true&allowPublicKeyRetrieval=true&useSSL=false spring.datasource.username=test_user_id spring.datasource.password=test_user_pwd # 连接池配置 spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 spring.datasource.maxWait=60000 spring.datasource.timeBetweenEvictionRunsMillis=60000 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 打开PSCache,并且指定每个连接上PSCache的大小 spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计 # "stat,wall,log4j"中的wall用于防火墙,如果开启,那么无法执行多条SQL语句;log4j也应该去掉,因为新版的配置已经发生改变 spring.datasource.filters=stat spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合并多个DruidDataSource的监控数据 #spring.datasource.useGlobalDataSourceStat=true # mybatis配置 mybatis.type-aliases-package=com.namejr.bean mybatis.mapper-locations=classpath:/dao/*.xml # 配置(Nacos服务)名称 spring.application.name=consumer # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:18848 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # 心跳由默认的5s改为10s spring.cloud.nacos.discovery.heart-beat-interval=10000 # 心跳由默认的15s改为20s。在20s没有收到客户端的心跳就认为客户端不不健康状态 spring.cloud.nacos.discovery.heart-beat-timeout=20000 # 如果超过60s没有收到客户端的心跳,nacos服务端变会把客户端的服务实例删除。 spring.cloud.nacos.discovery.ip-delete-timeout=60000
BalanceRestTemplateConfig.java
package com.namejr.base; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /* 负载均衡的RestTemplate */ @Configuration public class BalanceRestTemplateConfig { @Bean @LoadBalanced public RestTemplate getLoadBalancedRestTemplate(){ return new RestTemplate(); } }
PublicController.java
package com.namejr.controller; import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping(value = "/api/public") @Tag(name = "PublicController", description = "通用公共控制器") @RefreshScope public class PublicController { private static final Logger logger = LoggerFactory.getLogger(PublicController.class); // 因为和非负载均衡Bean(getRestTemplate)冲突,故使用QualiFier限定 @Qualifier("getLoadBalancedRestTemplate") @Autowired private RestTemplate brestTemplate; @RequestMapping(value = "/getStringByLoadBalanced", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String serviceTime() { // 格式: http://服务名称/port return brestTemplate.getForObject("http://publicCould/api/public/runNacosConfig",String.class); } }

三、网关
子模块截图

pom.xml
<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> <parent> <groupId>com.namejr</groupId> <artifactId>Web_GatherCould</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>Web_GatewayCould</artifactId> <packaging>jar</packaging> <name>Web_GatewayCould</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 添加网关依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- 添加 Spring Boot Actuator 监控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 如果配置中要使用lb://URL,那么这里的负载均衡需要显示依赖进去 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
application.properties(法一:通过配置文件配置网关,下面有通过bean进行配置的,目前没使用)
# 端口号 server.port=11100 # 配置日志 logging.config=classpath:logback-spring.xml # actuator 监控 http://localhost:11100/actuator/gateway/routes management.endpoints.web.exposure.include=* # 配置(Nacos服务)名称 spring.application.name=gateway # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:18848 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # 心跳由默认的5s改为10s spring.cloud.nacos.discovery.heart-beat-interval=10000 # 心跳由默认的15s改为20s。在20s没有收到客户端的心跳就认为客户端不不健康状态 spring.cloud.nacos.discovery.heart-beat-timeout=20000 # 如果超过60s没有收到客户端的心跳,nacos服务端变会把客户端的服务实例删除。 spring.cloud.nacos.discovery.ip-delete-timeout=60000 # 网关相关配置 # 在application.yml中将web应用类型设置为REACTIVE: spring.main.web-application-type=reactive # gateway开启服务注册和发现功能,并自动根据服务发现每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务 # spring.cloud.gateway.discovery.locator.enabled=true # 是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了),比如以/service-hi/*的请求路径被路由转发到服务名为service-hi的服务上。 # spring.cloud.gateway.discovery.locator.lower-case-service-id=true # id:唯一即可 spring.cloud.gateway.routes[0].id=publicCould # 路由目标地址 # 方式一:spring.cloud.gateway.routes[0].uri=http://127.0.0.1:11101 # 方式二:使用负载均衡,格式:lb://+服务名称 spring.cloud.gateway.routes[0].uri=lb://publicCould # 路由断言,也就是路由规则,符合下面的路由规则将会使用对应routes下的uri,如本例子就会路由到routes[0].uri=lb://publicCould spring.cloud.gateway.routes[0].predicates[0]=Path=/wpc/** spring.cloud.gateway.routes[1].id=consumer spring.cloud.gateway.routes[1].uri=lb://consumer spring.cloud.gateway.routes[1].predicates[0]=Path=/wc/**
StartApplication.java
package com.namejr; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication public class StartApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(StartApplication.class, args); } protected SpringApplicationBuilder configuer(SpringApplicationBuilder builder) { return super.configure(builder); } }
访问各个服务,直接通过11100网关所在模块端口访问各个模块。

法二:通过bean进行配置的,目前没使用
base/GatewayRouterConfig.java
package com.namejr.base; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayRouterConfig { @Bean public RouteLocator routeLocator(RouteLocatorBuilder locatorBuilder){ final RouteLocatorBuilder.Builder routes = locatorBuilder.routes(); routes.route(baidu-> baidu.path("/wpc/**").uri("lb://publicCould")); return routes.build(); } }
各种详细配置,可以查看该文章,写得比较详细:springcloud 入门 之网关 springcloud gateway - 码猿笔记 - 博客园 (cnblogs.com)
四、熔断
另注:下面采用的是properties的配置方式,如果需要使用重写Bean的方式,可以参照该博客:使用Spring Cloud和Resilience4j实现微服务容错与降级
pox.xml
<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> <parent> <groupId>com.namejr</groupId> <artifactId>Web_GatherCould</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>Web_Consumer</artifactId> <packaging>jar</packaging> <name>Web_Consumer</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- nacos注册中心子服务依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 引入负载均衡处理 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!-- 熔断器:resilience4j --> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> </dependency> <!-- 需要引入aop,否则@CircuitBreaker不生效 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies> </project>
目标服务Web_PublicCould的serviceTime模拟耗时
@RequestMapping(value = "/serviceTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String serviceTime() { try{ Thread.sleep(10000); }catch (Exception err){} return DateTime.now().toString("yyyy-MM-dd HH:mm:ss"); }
application.properties
# 端口号 server.port=11102 # 配置日志 logging.config=classpath:logback-spring.xml # 配置(Nacos服务)名称 spring.application.name=consumer # Nacos服务注册中心地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:18848 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # 心跳由默认的5s改为10s spring.cloud.nacos.discovery.heart-beat-interval=10000 # 心跳由默认的15s改为20s。在20s没有收到客户端的心跳就认为客户端不不健康状态 spring.cloud.nacos.discovery.heart-beat-timeout=20000 # 如果超过60s没有收到客户端的心跳,nacos服务端变会把客户端的服务实例删除。 spring.cloud.nacos.discovery.ip-delete-timeout=60000 # 1、断路器 # slidingWindowSize用于定义滑动窗口的大小,直接影响失败率计算和熔断触发条件。 # 滑动窗口大小:控制统计失败请求的样本数量,窗口越大,熔断触发越谨慎。 # 失败率计算:当窗口内失败请求占比超过阈值(如50%)时触发熔断。 # 默认值:slidingWindowSize=100(可通过resilience4j.circuitbreaker.configs.default.slidingWindowSize修改)。 # 自定义设置:例如设置为6,表示每次统计最近3次请求的失败率。 # 窗口未满时:即使失败率超过阈值,熔断也不会触发(需满足minimumNumberOfCalls)。 # 窗口满后:失败率超过阈值立即熔断,例如6次请求中3次失败即触发。 resilience4j.circuitbreaker.instances.consumerService.sliding-window-size=6 # 设置了类型以根据请求计数保持断路器行为。 resilience4j.circuitbreaker.instances.consumerService.sliding-window-type=COUNT_BASED # 决定启用断路器的失败百分比的 API 调用总数的最小值。我将其设置为5。假设前 5 个 API 调用中有 3 个 API 调用失败。这意味着 failureRateThreshold = (3/5) * 100 = 60%。 resilience4j.circuitbreaker.instances.consumerService.minimum-number-of-calls=5 # failureRateThreshold是熔断器触发保护机制的核心参数,用于判断服务是否因异常失败而需要熔断。默认值为50%,即当失败调用占比超过该阈值时,熔断器会从关闭状态切换到打开状态,拒绝后续请求。 # 阈值定义与计算: # 公式:失败率 = (失败调用数 ÷ 总调用数) × 100% # 触发条件:失败率 ≥ 阈值(如50%)时触发熔断。 resilience4j.circuitbreaker.instances.consumerService.failure-rate-threshold=50 # 当转换的正确时间到来时,它会自动将 OPEN 状态转换为 HALF OPEN 状态。 resilience4j.circuitbreaker.instances.consumerService.automatic-transition-from-open-to-half-open-enabled=true # waitDurationInOpenState用于指定断路器从OPEN状态切换到HALF_OPEN状态的等待时间,单位毫秒。此配置使断路器在熔断后5秒内尝试恢复。 resilience4j.circuitbreaker.instances.consumerService.wait-duration-in-open-state=5000 # 在 HALF OPEN 状态下应发送的 LIMITED API 调用数。我将其设置为 3。因此,在 3 次 API 调用之后,如果失败,则断路器将再次进入 OPEN 状态。否则断路器将关闭,因为 rate-service 已启动。 resilience4j.circuitbreaker.instances.consumerService.permitted-number-of-calls-in-half-open-state=3 # ringBufferSizeInClosedState在关闭状态(CLOSED)下的环状缓冲区大小,用于记录请求的成功/失败状态。默认值为100,表示熔断器会统计最近100次请求的失败率来判断是否触发熔断。 # 失败率计算:熔断器通过缓冲区中的请求数据计算失败率。若缓冲区未填满(请求次数低于缓冲区大小),即使失败率超过阈值,也不会触发熔断。 # 阈值触发条件:失败率需达到failureRateThreshold(默认50%)且缓冲区已填满时,熔断器才会切换到OPEN状态。 resilience4j.circuitbreaker.instances.consumerService.ring-buffer-size-in-closed-state=5 # ringBufferSizeInHalfOpenState用于定义熔断器在半开状态(HALF_OPEN)下允许通过的请求数量,直接影响熔断器状态转换和故障恢复效率。 # 状态转换:当熔断器处于打开状态(OPEN)时,经过等待时间(waitDurationInOpenState)后会进入半开状态。此时,熔断器会允许最多ringBufferSizeInHalfOpenState个请求通过,根据这些请求的成功率决定是否恢复关闭状态(CLOSED)或重新进入打开状态 。 默认值:默认值为10,表示半开状态下最多允许10个请求通过 。 resilience4j.circuitbreaker.instances.consumerService.ring-buffer-size-in-half-open-state=3 # 2、限流器 # limitForPeriod用于定义每个刷新周期内允许的最大请求数。以下是核心要点: # 作用:控制单位时间(由limitRefreshPeriod指定)内允许的最大请求次数。 # 示例:若limitForPeriod=2且limitRefreshPeriod=1s,则每秒最多允许2个请求。 resilience4j.ratelimiter.instances.consumerService.limit-for-period=2 # 用于定义令牌刷新的时间间隔,单位为毫秒(ms),默认值为500ms。 # 核心作用: # 控制令牌刷新频率:在指定时间间隔内,系统会重新生成一定数量的令牌(由limitForPeriod定义),用于限制请求速率。 # 与limitForPeriod共同决定限流速率:例如,若limitRefreshPeriod=1s且limitForPeriod=2,则每秒最多允许2个请求。 resilience4j.ratelimiter.instances.consumerService.limit-refresh-period=1s # 通常指请求在获取令牌时的最大等待时间,超过该时间则触发超时。具体实现和配置取决于使用的库(如Resilience4j或Guava)。 # 信号量模式:通过Semaphore限制并发请求数,超时后直接返回失败。 # 线程池模式:通过线程池限制并发数,超时后返回失败。 resilience4j.ratelimiter.instances.consumerService.timeout-duration=100ms # 3、重试 # maxAttempts参数用于配置最大重试次数(包含初始调用)。 resilience4j.retry.instances.consumerService.max-attempts=3 # waitDuration用于配置重试间隔时间,即两次重试尝试之间的等待时长。默认值:若未显式配置,默认等待时长为500毫秒(500ms)。 resilience4j.retry.instances.consumerService.wait-duration=500ms
BalanceRestTemplateConfig.java
package com.namejr.base; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; /* 负载均衡的RestTemplate */ @Configuration public class BalanceRestTemplateConfig { // 不推荐使用,但是可以使用 @Bean @LoadBalanced public RestTemplate getLoadBalancedRestTemplate(){ SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(10000); // 设置连接超时时间(毫秒) requestFactory.setReadTimeout(10000); // 设置读取超时时间(毫秒) return new RestTemplate(requestFactory); // return new RestTemplate(); } /* 推荐使用,目前还没用:在这个例子中,我们使用了WebClient,它是响应式编程的一部分,非常适合与Spring Cloud Load // pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> // 引入: import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient.RequestBodyUriSpec; import reactor.core.publisher.Mono; // 配置bean: @Bean @LoadBalanced public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); } // 使用案例: @Autowired private WebClient.Builder webClientBuilder; public Mono<String> postData(String url, Map<String, Object> requestBody) { return webClientBuilder .build() .post() .uri("http://SERVICE-NAME/api/path") .body(Mono.just(requestBody), Map.class) .retrieve() .bodyToMono(String.class); } */ }
PublicController.java
package com.namejr.controller; import com.namejr.service.PublicCouldService; import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/wc/public") @Tag(name = "PublicController", description = "通用公共控制器") public class PublicController { private static final Logger logger = LoggerFactory.getLogger(PublicController.class); @Autowired private PublicCouldService pcService; @RequestMapping(value = "/getStringByLoadBalanced", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String stringByLoadBalanced() { return pcService.runNacosConfig(); } @RequestMapping(value = "/serviceTime", method = RequestMethod.GET,produces = "application/json;charset=UTF-8") public String serviceTime() { return pcService.serviceTime(); } }
PublicCouldService.java
package com.namejr.service; import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class PublicCouldService { @Qualifier("getLoadBalancedRestTemplate") @Autowired private RestTemplate brestTemplate; public String runNacosConfig(){ // get请求,格式: http://服务名称/port return brestTemplate.getForObject("http://publicCould/wpc/public/runNacosConfig",String.class); /** post请求: * HttpHeaders headers = new HttpHeaders(); * headers.setContentType(MediaType.APPLICATION_JSON); * HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers); * restTemplate.postForObject("http://SERVICE-NAME/api/path", entity, String.class); * */ }
// 测试断路器 @CircuitBreaker(name = "consumerService",fallbackMethod = "serviceTimeOfCircuitBreaker") public String serviceTime(){ return "正常返回:"+brestTemplate.getForObject("http://publicCould/wpc/public/serviceTime",String.class); } /** 注意:@CircuitBreaker声明fallbackMethod方法时,参数需要Exception,否则会报下面错误:NoSuchMethodException * 2025-11-29 16:56:24.037 ERROR -- [io-11102-exec-2] [.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause * java.lang.NoSuchMethodException: class java.lang.String class com.namejr.service.PublicCouldService.serviceTimeOfCircuitBreaker(,class java.lang.Throwable) * */ public String serviceTimeOfCircuitBreaker(Exception err){ System.out.println(err.getMessage()); return "熔断返回:"+ DateTime.now().toString("yyyy-MM-dd HH:mm:ss"); } }
/** 模拟异常 * 断路器:@CircuitBreaker * 限流:@RateLimiter * 重试:@Retry * */ @CircuitBreaker(name = "consumerService",fallbackMethod = "serviceTimeOfCircuitBreaker") @RateLimiter(name = "consumerService") @Retry(name = "consumerService") public String serviceTime(){ return "正常返回:"+brestTemplate.getForObject("http://publicCould/wpc/public/serviceTime",String.class); }
访问http://127.0.0.1:11100/wc/public/serviceTime


。。。待续。
浙公网安备 33010602011771号