文章目录
- 🔊博主介绍
- 🥤本文内容
- 📢文章总结
- 📥博主目标
🔊博主介绍
🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文专业写手、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。🌎跑过十五公里、🚀徒步爬过衡山、🔥有过三个月减肥20斤的经历、是个喜欢躺平的狠人。
📕拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、Spring MVC、SpringCould、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RockerMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。
📙有过从0到1的项目高并发项目开发与管理经验,对JVM调优、MySQL调优、Redis调优 、ElasticSearch调优、消息中间件调优、系统架构调优都有着比较全面的实战经验。
📘有过云端搭建服务器环境,自动化部署CI/CD,弹性伸缩扩容服务器(最高200台),了解过秒级部署(阿里云的ACK和华为云的云容器引擎CCE)流程,能独立开发和部署整个后端服务,有过分库分表的实战经验。
🎥经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧,与清华大学出版社签下了四本书籍的合约,并将陆续在明年出版。这些书籍包括了基础篇、进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码–沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!
文章目录
- 🔊博主介绍
- 🥤本文内容
- 📢文章总结
- 📥博主目标
🌾阅读前,快速浏览目录和章节概览可帮助了解文章结构、内容和作者的重点。了解自己希望从中获得什么样的知识或经验是非常重要的。建议在阅读时做笔记、思考问题、自我提问,以加深理解和吸收知识。
💡在这个美好的时刻,本人不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。
🥤本文内容
官方地址:https://github.com/resilience4j/resilience4j
resilience4j 2.0.0版本使用门槛最低都是jdk17,官网介绍:
Resilience4j is a lightweight fault tolerance library designed for functional programming. Resilience4j provides higher-order functions (decorators) to enhance any functional interface, lambda expression or method reference with a Circuit Breaker, Rate Limiter, Retry or Bulkhead. You can stack more than one decorator on any functional interface, lambda expression or method reference. The advantage is that you have the choice to select the decorators you need and nothing else.Resilience4j 2 requires Java 17.
文档地址:https://resilience4j.readme.io/v2.0.0/docs/getting-started
而从jdk1.8升级到17,项目很多依赖都要调整,同时由于对应的springboot,springcloud,springcloudalibaba版本的升级导致很多代码需要重写,Spring Boot 2.5.x 之前的版本确实不支持 Java 17。这是因为 Spring Boot 2.3 依赖于 Spring Framework 5.2,后者使用了与 Java 17 不兼容的 CGLIB 和 ASM 版本。然而,从 Spring Boot 2.5.5 开始,Spring Boot 开始支持 Java 17。Spring Boot 2.5.5 是第一个支持 Java 17 的 Spring Boot 版本。如果想使用 Java 17 和更早版本的 Spring Boot,需要进行一些额外的配置或调整。这可能包括使用兼容的库版本、手动修改依赖关系或进行一些代码更改。但是,请注意,这可能会导致一些兼容性问题或功能限制。Spring Boot 3.0是全面放弃JDK8,全面支持JDK17,且最低支持版本就是JDK17。所以对于一些新项目而言,如果升级版本,不如一次性到位,升级到Spring Boot 3.0。对于一些老项目升级,就比较麻烦了,很多依赖和代码可能面临重新或者代码调整的情况,试错成本挺高的。
举个例子,原先使用WebSocket,javax.websocket 是 Java EE 7提供的 WebSocket API,正常SpringBoot2.3.12.RELEASE版本即可使用,升级版本到Spring Boot 3.x 版本,通常使用更现代的替代方案,即基于 Project Reactor 和 Netty 的 WebSocket 支持。 在 Spring Boot 2.x 中,spring-boot-starter-websocket 依赖提供了对 Java EE WebSocket API 的支持,因此你可以直接使用 javax.websocket。但在 Spring Boot 3.x 中,情况发生了变化,Spring Boot 转向了更加反应式和异步的编程模型,因此它不再直接支持 Java EE WebSocket API,所以需要重写代码。
除此之外,还有很多配置也需要调整,例如nacos会报错。
Description:No spring.config.import property has been definedAction:Add a spring.config.import=nacos: property to your configuration.If configuration is not required add spring.config.import=optional:nacos: instead.To disable this check, set spring.cloud.nacos.config.import-check.enabled=false.Disconnected from the target VM, address: '127.0.0.1:49823', transport: 'socket'Process finished with exit code 1
这个错误信息表明你的 Spring Boot 应用程序中没有定义 spring.config.import 属性,而这个属性对于使用 Nacos 作为配置中心来说是必需的。要解决这个问题,需要在配置文件中(通常是 bootstrap.yml 或 bootstrap.properties)添加 spring.config.import 属性,并指向你的 Nacos 配置。这个属性告诉 Spring Boot 应用程序从哪个 Nacos 服务器和哪个命名空间中加载配置。这里是一个例子,展示了如何在 bootstrap.yml 文件中添加 spring.config.import 属性:
spring: application: name: your-application-name cloud: nacos: config: server-addr: your-nacos-server-address # Nacos 服务器地址 namespace: your-namespace-id # Nacos 命名空间 ID group: your-group-name # Nacos 配置分组名 config: import: nacos://your-nacos-server-address?namespace=your-namespace-id&group=your-group-name
在这个例子中,spring.config.import 属性的值是一个 URI,它告诉 Spring Boot 应用程序从指定的 Nacos 服务器、命名空间和分组中加载配置。如果不想使用 Nacos 作为配置中心,而是想禁用这个检查,你可以设置 spring.cloud.nacos.config.import-check.enabled 属性为 false,如下所示:
spring: cloud: nacos: config: import-check: enabled: false
请确保你的 Nacos 服务器正在运行,并且你的应用程序可以访问它。同时,检查你的 Nacos 配置是否正确,包括服务器地址、命名空间 ID 和配置分组名。如果问题仍然存在,你可能需要检查你的网络设置,确保应用程序可以正确连接到 Nacos 服务器。
博主也调整了配置:
# 本地环境配置:
# bootstrap.yml优先级比application.yml优先级高
spring:# prefix-{spring.profile.active}.${file-extension}# Nacos会根据当前环境去拼接配置名称查找相应配置文件,# 示例:{spring.application.name}-{spring.profiles.active}-{spring.cloud.nacos.config.file-extension}# 获取到值:red-package-rain-api-dev.yaml# Nacos会根据当前环境和file-extension参数去拼接配置文件名称profiles:# 本地环境local,开发环境dev,测试环境test,生产环境prod# 当前活动的配置文件为devactive: local# 应用名称application:name: red-package-rain-api# spring.config.import属性的值是一个以nacos://开头的URI,后面跟着Nacos服务器的地址和可选的命名空间及分组信息。这些信息将告诉Spring Cloud应用程序从哪个Nacos服务器和哪个命名空间中加载配置。config:
# import: nacos://${spring.cloud.nacos.config.server-addr}?namespace=${spring.cloud.nacos.config.namespace}&group=${spring.cloud.nacos.config.group} import: nacos://192.168.80.101:8848?namespace=21c790b2-0b30-4433-a030-245f17203d2f&group=RED_PACKAGE_RAIN_LOCAL_GROUP #避免受占位符影响cloud:nacos:discovery:# 服务注册地址server-addr: 192.168.80.101:8848config:import-check:enabled: false#nacos配置中心地址server-addr: 192.168.80.101:8848#配置中心的命名空间id localnamespace: 21c790b2-0b30-4433-a030-245f17203d2f#配置分组,默认没有也可以 LOCALgroup: RED_PACKAGE_RAIN_LOCAL_GROUP#配置文件后缀,用于拼接配置配置文件名称,目前只支持yaml和propertiesfile-extension: yaml#配置自动刷新refresh-enabled: true#配置文件的前缀,默认是application.name的值,如果配了prefix,就取prefix的值prefix: red-package-rain-api-local# 配置编码encode: UTF-8# 用户名username: nacos# 密码password: nacos
调整配置之后,依然相同的错误,分析问题:
从您提供的配置和错误信息来看,您已经定义了 spring.config.import 属性,并指向了 Nacos 配置中心。然而,错误信息表明 Spring Boot 应用程序没有找到 spring.config.import 属性的定义。这可能是由于以下几个原因:
-
配置文件的格式或缩进问题:YAML 文件对格式和缩进非常敏感。请确保您的配置文件的缩进是正确的,通常使用两个空格进行缩进。(排除)
-
配置文件位置问题:spring.config.import 应该在正确的配置文件中定义。通常,这个属性放在 bootstrap.yml 或者 bootstrap.properties 文件中,因为这些文件在应用程序上下文初始化时加载,早于 application.yml 或 application.properties。(排除)
-
占位符未解析:虽然您在 spring.config.import 中避免了使用占位符(如 ${spring.cloud.nacos.config.server-addr}),但请确保其他部分的占位符(如 spring.cloud.nacos.config.server-addr、spring.cloud.nacos.config.namespace、spring.cloud.nacos.config.group)在您的配置文件中能够被正确解析。(排除)
-
配置文件加载顺序:如果 bootstrap.yml 和 application.yml 都存在,并且两者都有相同的配置项,那么 bootstrap.yml 中的配置会优先被加载。请确保 spring.config.import 仅在 bootstrap.yml 中定义(如果您打算使用它)。(排除)
-
配置文件可见性:确保配置文件(bootstrap.yml 或 bootstrap.properties)放在类路径的根目录下,这样 Spring Boot 应用程序可以加载到它。(排除)
-
Nacos 服务器问题:虽然错误信息是关于 spring.config.import 的,但请确保 Nacos 服务器正在运行,并且您的应用程序可以访问它。如果 Nacos 服务器不可达,即使 spring.config.import 定义了,也可能导致配置加载失败。(排除)
-
版本兼容性问题:请检查您使用的 Spring Cloud 和 Nacos Config 的版本是否兼容。不同版本的库可能会有不同的配置要求。(无法排除,官方文档未作说明)
这也导致为了使用这个流控组件2.0.0版本需要调整的地方多于使用其他主流的流控组件,试错成本太高了,得不偿失。
然后我减低版本,使用2.0.0以下版本(不包括2.0.0)才能使用jdk1.8,文档地址:
https://resilience4j.readme.io/v1.7.0/docs/comparison-to-netflix-hystrix-1
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><!--引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。jdk1.8版本使用在https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系--><spring.boot.version>2.3.12.RELEASE</spring.boot.version><spring.cloud.version>Hoxton.SR12</spring.cloud.version><spring.cloud.alibaba.version>2.2.7.RELEASE</spring.cloud.alibaba.version>--></properties><!--引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系--><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring.cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring.cloud.alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>1.7.0</version></dependency></dependencies>
对应的配置,和2.0.0版本也有细微差别:
resilience4j:retry: # 重试策略机制配置instances: # 定义多个重试策略实例retryApi: # 第一个重试策略重试名称max-attempts: 3 # 操作失败最大重试次数为3wait-duration: 1s # 每次重试等待时间1秒circuitbreaker:instances: # 定义多个断路器实例circuitBreakerApi: # 第一个断路器实例名称registerHealthIndicator: true # 配置健康指示器slidingWindowSize: 10 # 滑动窗口大小minimumNumberOfCalls: 5 # 最小调用次数permittedNumberOfCallsInHalfOpenState: 3 # 半开状态下允许的调用次数slidingWindowType: TIME_BASED # 滑动窗口类型automaticTransitionFromOpenToHalfOpenEnabled: true # 是否自动从开启状态转换为半开状态waitDurationInOpenState: 1s # 开启状态下等待时间failureRateThreshold: 20 # 失败率阈值,失败率20%时,断路器打开eventConsumerBufferSize: 10 # 事件消费者缓冲区大小ignoreExceptions: # 忽略的异常列表- java.io.IOExceptionratelimiter:instances: # 定义多个限流策略实例rateLimiterApi: # 第一个限流策略实例名称limitForPeriod: 10000 # 限制周期内的请求数量10000limitRefreshPeriod: 10s # 限制刷新周期,10秒一个周期timeoutDuration: 500ms # 超时时间为0.5秒,请求超过限制客户端立即收到超时响应,不等待subscribeForEvents: AFTER_SUCCESS # 订阅事件eventConsumerBufferSize: 10 # 事件消费者缓冲区大小
subscribeForEvents: AFTER_SUCCESS改为subscribeForEvents: true
resilience4j:retry: # 重试策略机制配置instances: # 定义多个重试策略实例retryApi: # 第一个重试策略重试名称max-attempts: 3 # 操作失败最大重试次数为3wait-duration: 1s # 每次重试等待时间1秒circuitbreaker:instances: # 定义多个断路器实例circuitBreakerApi: # 第一个断路器实例名称registerHealthIndicator: true # 配置健康指示器slidingWindowSize: 10 # 滑动窗口大小minimumNumberOfCalls: 5 # 最小调用次数permittedNumberOfCallsInHalfOpenState: 3 # 半开状态下允许的调用次数slidingWindowType: TIME_BASED # 滑动窗口类型automaticTransitionFromOpenToHalfOpenEnabled: true # 是否自动从开启状态转换为半开状态waitDurationInOpenState: 1s # 开启状态下等待时间failureRateThreshold: 20 # 失败率阈值,失败率20%时,断路器打开eventConsumerBufferSize: 10 # 事件消费者缓冲区大小ignoreExceptions: # 忽略的异常列表- java.io.IOExceptionratelimiter:instances: # 定义多个限流策略实例rateLimiterApi: # 第一个限流策略实例名称limitForPeriod: 10000 # 限制周期内的请求数量10000limitRefreshPeriod: 10s # 限制刷新周期,10秒一个周期timeoutDuration: 500ms # 超时时间为0.5秒,请求超过限制客户端立即收到超时响应,不等待subscribeForEvents: true # 订阅事件eventConsumerBufferSize: 10 # 事件消费者缓冲区大小
接口处代码不变
@Retry(name = "retryApi",fallbackMethod = "fallbackRedPackage")@CircuitBreaker(name = "circuitBreakerApi",fallbackMethod = "fallbackRedPackage")@RateLimiter(name = "rateLimiterApi",fallbackMethod = "fallbackRedPackage")@PostMapping(value = "/redPackage")public Result redPackage(@RequestBody RedPackegeRainVo redPackage) throws Exception{// TODO do sometingreturn Result.error(ResultCodeEnum.RED_PACKAGE_FINISHED.getCode(),ResultCodeEnum.RED_PACKAGE_FINISHED.getMessage());}
📢文章总结
对本篇文章进行总结:
🔔以上就是今天要讲的内容,阅读结束后,反思和总结所学内容,并尝试应用到现实中,有助于深化理解和应用知识。与朋友或同事分享所读内容,讨论细节并获得反馈,也有助于加深对知识的理解和吸收。
🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~
🚀🎉希望各位读者大大多多支持用心写文章的博主,现在时代变了,🚀🎉 信息爆炸,酒香也怕巷子深🔥,博主真的需要大家的帮助才能在这片海洋中继续发光发热🎨,所以,🏃💨赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: 我是廖志伟
- 👉开源项目:java_wxid
- 🌥 哔哩哔哩:我是廖志伟
- 🎏个人社区:幕后大佬
- 🔖个人微信号:
SeniorRD
- 🎉微信号二维码:
📥博主目标
- 🍋程序开发这条路不能停,停下来容易被淘汰掉,吃不了自律的苦,就要受平庸的罪,持续的能力才能带来持续的自信。我本是一个很普通的程序员,放在人堆里,除了与生俱来的盛世美颜,就剩180的大高个了,就是我这样的一个人,默默写博文也有好多年了。
- 📺有句老话说的好,牛逼之前都是傻逼式的坚持,希望自己可以通过大量的作品、时间的积累、个人魅力、运气、时机,可以打造属于自己的技术影响力。
- 💥内心起伏不定,我时而激动,时而沉思。我希望自己能成为一个综合性人才,具备技术、业务和管理方面的精湛技能。我想成为产品架构路线的总设计师,团队的指挥者,技术团队的中流砥柱,企业战略和资本规划的实战专家。
- 🎉这个目标的实现需要不懈的努力和持续的成长,但我必须努力追求。因为我知道,只有成为这样的人才,我才能在职业生涯中不断前进并为企业的发展带来真正的价值。在这个不断变化的时代,我们必须随时准备好迎接挑战,不断学习和探索新的领域,才能不断地向前推进。我坚信,只要我不断努力,我一定会达到自己的目标。
🔔有需要对自己进行综合性评估,进行职业方向规划,我可以让技术大牛帮你模拟面试、针对性的指导、传授面试技巧、简历优化、进行技术问题答疑等服务。
可访问:https://java_wxid.gitee.io/tojson/