前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >淘宝上传图片api报了“HSF thread pool is full”,很烦但问题还要解!幸亏有这个组件轻松搞定

淘宝上传图片api报了“HSF thread pool is full”,很烦但问题还要解!幸亏有这个组件轻松搞定

作者头像
烟雨平生
发布于 2024-12-20 06:41:10
发布于 2024-12-20 06:41:10
13600
代码可运行
举报
文章被收录于专栏:数字化之路数字化之路
运行总次数:0
代码可运行

又又又报错了:

发现淘宝和微信都是一个德行,对客端的页面和交互对用户各种谄媚,各种小惊喜,各种体验优化,各种暖心交互,各种闭环;对商端做的真是一坨屎,没有提供场景化完成一个功能的文档,满眼都是鸡零狗碎的东一个西一个的API,文档页面看着老旧丑陋没有技术含量,并且不好找,找个功能需要找半天,没有闭环想用个功能需要各种申请,烦死个人。权限开通后,一个不小心权限就被封功能不能用,又是各种申诉各种整改,憋屈。气死个人。

吐槽又不能解决问题。先来看看这个报错吧。好在淘宝还可以提工单,这点比微信更有助于解决遇到的问题。

淘宝说我就是这样,也不怕你重试,你再来多请求几次呀!!

既然淘宝方案给了,那就增加重试吧。

自己写一个for循环+sleep来完成重试有些slow+花时间,感觉还是用现成的组件进行重试更优雅。

之前做过技术选型,选了Spring Retry。Spring Retry就不在这展开介绍了,详见文末。

要在Spring框架中基于Spring-Retry实现接口抛异常后的Retryable功能,可以遵循以下步骤:

添加依赖

首先,你需要在你的Spring Boot项目的pom.xml文件中添加spring-retry的依赖。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 重试相关依赖包 -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.3.4</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

开启重试功能

默认是不开启的。

在你的Spring Boot应用的主启动类上添加@EnableRetry注解,以开启重试机制的支持。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication
@EnableRetry
public class RetryApplication {
    public static void main(String[] args) {
        SpringApplication.run(RetryApplication.class, args);
    }
}

声明式配置重试策略

使用@Retryable注解:

在需要实现重试的方法上添加@Retryable注解,这样当方法抛出指定异常时,就会自动进行重试。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.util.concurrent.ThreadLocalRandom;

@Service
@Slf4j
public class RetryServiceImpl implements RetryService {    

@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 1.5))    
@Override    
public String doBiz() {        
int countVal = ThreadLocalRandom.current().nextInt(10);        
if (countVal > 1) {            
// 这里可以使自定义异常,@Retryable中value需与其一致            
log.warn("doBiz 执行业务代码失败 countVal {} ", countVal); 
           throw new RuntimeException("执行业务代码失败");        
           }        
           log.info("doBiz 执行业务代码成功 countVal {} ", countVal);        
           return "success";    
        }    
    }



}

翻译一下:

在上面的例子中,@Retryable注解的参数含义如下:

  • value:指定重试的异常类型,这里是Exception,表示当抛出Exception类型异常时会触发重试。
  • maxAttempts:最大重试次数,这里是3次(包括第一次尝试)。
  • backoff:重试的间隔策略,delay指定了第一次重试的延迟时间(1000毫秒),multiplier指定了延迟时间的增长倍数(1.5倍)。

可视化调试过程

启用详细的日志记录:

在Spring的配置中启用DEBUG级别的日志,这样可以查看Spring Retry的内部工作情况,包括代理创建和重试逻辑。可视化的看到重试的过程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 在application.properties或application.yml中添加
logging.level.org.springframework.retry=DEBUG

光说不练假把式

写个测试用例,Run起来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import com.tangcheng.toolbox.ToolBoxApplication;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest(classes = ToolBoxApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
class RetryServiceImplTest {   
 
    @Autowired    
    private RetryService retryService;  
  
    @Test    
    void doBiz() {
        String result = retryService.doBiz();
        log.info("result {} ", result);   
    }      
}

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2024-12-10 21:21:24.749  INFO 22518 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 65177 (http) with context path ''
2024-12-10 21:21:24.760  INFO 22518 --- [           main] c.t.t.b.tool.RetryServiceImplTest        : Started RetryServiceImplTest in 2.932 seconds (JVM running for 4.005)
2024-12-10 21:21:24.991 DEBUG 22518 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=0
2024-12-10 21:21:24.999  WARN 22518 --- [           main] c.t.t.business.tool.RetryServiceImpl     : doBiz 执行业务代码失败 countVal 7 
2024-12-10 21:21:24.999 DEBUG 22518 --- [           main] o.s.r.backoff.ExponentialBackOffPolicy   : Sleeping for 1000
2024-12-10 21:21:26.004 DEBUG 22518 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=1
2024-12-10 21:21:26.004 DEBUG 22518 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=1
2024-12-10 21:21:26.004  INFO 22518 --- [           main] c.t.t.business.tool.RetryServiceImpl     : doBiz 执行业务代码成功 countVal 0 
2024-12-10 21:21:26.004  INFO 22518 --- [           main] c.t.t.b.tool.RetryServiceImplTest        : result success 

第二次重试时成功了

可以看到,Spring Retry的debug日志与业务代码中打印日志是一致的。

正常情况下,生产环境是不会开debug日志的,想在重试失败时进行一些操作,譬如打印特殊的日志,譬如发一条告警通知,需要怎么做?在加了@Retryable注解的方法中直接加,肯定是不行的。至于原因,各位大佬想一下为什么

实际上,这种场景Spring Retry也是支持的。你可以使用@Recover注解来指定一个方法,当重试次数耗尽后,这个方法将被调用以进行异常恢复处理。

@Recover来兜底

@Recover注解用于标记一个方法,该方法会在@Retryable注解标记的方法重试后仍然失败时被调用。这个方法可以作为最后的防线,处理重试失败后的情况,比如记录日志、发送告警、或者返回一个默认值等。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Recover
public String doBizRecover(Exception e) {    
    log.warn("@Recover回调方法执行 重试后仍然没有成功");    
    return "报错了 " + e.getMessage();
}

多跑几次测试用例,尝试触发重试后仍然失败的场景:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2024-12-10 21:31:08.452  INFO 24877 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 50004 (http) with context path ''
2024-12-10 21:31:08.462  INFO 24877 --- [           main] c.t.t.b.tool.RetryServiceImplTest        : Started RetryServiceImplTest in 2.785 seconds (JVM running for 3.909)
2024-12-10 21:31:08.690 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=0
2024-12-10 21:31:08.696  WARN 24877 --- [           main] c.t.t.business.tool.RetryServiceImpl     : doBiz 执行业务代码失败 countVal 3 
2024-12-10 21:31:08.697 DEBUG 24877 --- [           main] o.s.r.backoff.ExponentialBackOffPolicy   : Sleeping for 1000
2024-12-10 21:31:09.701 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=1
2024-12-10 21:31:09.701 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=1
2024-12-10 21:31:09.702  WARN 24877 --- [           main] c.t.t.business.tool.RetryServiceImpl     : doBiz 执行业务代码失败 countVal 2 
2024-12-10 21:31:09.702 DEBUG 24877 --- [           main] o.s.r.backoff.ExponentialBackOffPolicy   : Sleeping for 1500
2024-12-10 21:31:11.207 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=2
2024-12-10 21:31:11.207 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=2
2024-12-10 21:31:11.208  WARN 24877 --- [           main] c.t.t.business.tool.RetryServiceImpl     : doBiz 执行业务代码失败 countVal 4 
2024-12-10 21:31:11.208 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=3
2024-12-10 21:31:11.208 DEBUG 24877 --- [           main] o.s.retry.support.RetryTemplate          : Retry failed last attempt: count=3
2024-12-10 21:31:11.209  WARN 24877 --- [           main] c.t.t.business.tool.RetryServiceImpl     : @Recover回调方法执行 重试后仍然没有成功
2024-12-10 21:31:11.209  INFO 24877 --- [           main] c.t.t.b.tool.RetryServiceImplTest        : result 报错了 执行业务代码失败 

Spring Retry的优点

Spring Retry 提供了一系列优点,使其成为处理暂时性故障和提高应用程序弹性的有力工具:

  1. 简化编码
    • 开发者无需手动编写重试逻辑,Spring Retry 通过注解和模板方法提供了重试的实现,大大简化了代码。
  2. 一致的API
    • 提供了一致的API来处理重试,无论是注解方式还是编程式方式,都遵循相同的设计原则。
  3. 灵活的重试策略
    • 支持自定义重试策略,包括重试次数、重试间隔(包括固定间隔和指数退避策略)以及重试条件。
  4. 异常处理
    • 允许开发者指定哪些异常应该触发重试,以及定义重试失败后的恢复逻辑。
  5. 集成AOP
    • 利用Spring AOP(面向切面编程),Spring Retry 可以在不修改业务逻辑代码的情况下,为方法添加重试功能。
  6. 状态管理
    • 支持有状态的重试,这意味着在重试过程中可以保留异常信息和重试状态。
  7. 兼容性
    • 与Spring生态系统中的其他组件(如Spring Data、Spring Integration)良好集成。
  8. 透明性
    • 对于调用者来说,重试是透明的,不需要关心重试的具体实现。
  9. 回退策略
    • 提供了在重试失败后执行的回退策略,允许开发者定义失败后的处理逻辑。
  10. 监听器支持
    • 通过实现RetryListener接口,可以在重试的不同阶段插入自定义逻辑,如记录日志、更新状态等。
  11. 可配置性
    • 允许在全局和方法级别配置重试参数,使得重试策略可以根据不同的业务需求进行调整。
  12. 提高可靠性
    • 对于可能由于网络问题或服务瞬时不可用而导致失败的操作,重试机制可以显著提高应用程序的可靠性。
  13. 减少人工干预
    • 自动化的重试减少了对人工干预的依赖,特别是在处理大量事务时。
  14. 易于测试
    • 由于重试逻辑被封装在Spring Retry中,可以更容易地编写单元测试集成测试

REFERENCE

阿里P7大佬首次分享Spring Retry不为人知的技巧https://zhuanlan.zhihu.com/p/37625630

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
初探Spring Retry
在与外部系统交互时,由网络抖动亦或是外部系统自身的短暂性问题触发的瞬时性故障是一个绕不过的坑,而重试可能是一个比较有效的避坑方案;但有一点需要特别注意:外部系统的接口是否满足幂等性,比如:尽管调用外部系统的下单接口超时了,但外部系统订单数据可能已经落库了,这个时候再重试一次,外部系统内的订单数据可能就重复了!
程序猿杜小头
2022/12/01
1.1K0
初探Spring Retry
java retry(重试) spring retry, guava retrying 详解
转载 自 http://blog.51cto.com/9250070/2156431
allsmallpig
2021/02/25
1.5K0
Spring-Retry重试实现原理
Spring实现了一套重试机制,功能简单实用。Spring Retry是从Spring Batch独立出来的一个功能,已经广泛应用于Spring Batch,Spring Integration, Spring for Apache Hadoop等Spring项目。本文将讲述如何使用Spring Retry及其实现原理。
程序猿DD
2020/12/08
1.8K0
Spring-Retry重试实现原理
Spring Retry
  在我们的业务场景中,经常要调用其他的API来获取信息,比如我们的业务场景需要依赖个人信息来处理,这个时候调用个人信息服务的API,但是由于可能同一时段多方在调用这个服务,可能该服务并发太多,没有及时响应我们的调用,我们的业务就不能执行下去,这个时候我们就需要重试机制了,当然 Spring 已经给我们提供了- Retry。  
haoming1100
2018/12/13
2.4K0
Spring-Retry重试实现原理,有点东西哈
> 公众号:[Java小咖秀](https://t.1yb.co/jwkk),网站:[javaxks.com](https://www.javaxks.com)
Java小咖秀
2021/03/24
9240
重学SpringBoot3-Spring Retry实践
Spring Retry是Spring生态系统中的一个重要组件,它提供了自动重试失败操作的能力。在分布式系统中,由于网络抖动、服务暂时不可用等临时性故障,重试机制显得尤为重要。本文将详细介绍如何在 SpringBoot 3 应用中集成和使用 Spring Retry。
CoderJia
2024/11/23
2630
重学SpringBoot3-Spring Retry实践
使用 Spring Boot 实现重试和补偿功能:从理论到实践
在分布式系统中,服务之间的调用可能会因为网络故障、服务器负载等原因偶尔失败。为了提高系统的可靠性和稳定性,我们经常需要实现重试和补偿功能。本文将介绍如何使用 Spring Boot 实现重试和补偿功能,并通过具体案例进行演示。
小马哥学JAVA
2024/06/17
7390
重试组件使用与原理分析(一)-spring-retry
在日常开发中,我们很多时候都需要调用二方或者三方服务和接口,外部服务对于调用者来说一般都是不可靠的,尤其是在网络环境比较差的情况下,网络抖动很容易导致请求超时等异常情况,这时候就需要使用失败重试策略重新调用 API 接口来获取。
叔牙
2020/11/19
3.8K0
重试组件使用与原理分析(一)-spring-retry
深入解析Google Guava库与Spring Retry重试框架
Guava库是Google提供的一套Java核心库,旨在增强Java集合、缓存、并发、I/O、字符串处理等核心功能。其中,Guava Retryer是Guava库的一个扩展组件,用于实现重试逻辑。
公众号:码到三十五
2024/03/19
5260
Spring Retry 教程
Spring Retry 是 Spring 提供的一个用于处理方法重试的库,它允许在遇到特定异常时自动重试方法的执行,这在处理可能由于瞬时故障导致失败的操作时真的非常非常有用(对于代码逻辑错误自然是重试多少次都没啥用哈_),由于Spring Retry 是通过面向切面编程(即 AOP)提供了一种声明式的重试机制,所以并不会侵入到业务逻辑代码中(so~推荐!)
闻说社
2024/09/18
1640
Spring Retry 教程
Spring-retry 使用指南
该项目为Spring应用程序提供声明式重试支持,它用于Spring Batch、Spring Integration、Apache Hadoop的Spring(以及其他),命令式重试也支持显式使用。
阿提说说
2022/12/02
1.4K0
确实很优雅,所以我要扯下这个注解的神秘面纱。
前几天我 Review 代码的时候发现项目里面有一坨逻辑写的非常的不好,一眼望去简直就是丑陋之极。
why技术
2022/02/17
4180
确实很优雅,所以我要扯下这个注解的神秘面纱。
Retrying_Library_For_Java
最近在github上看到一个得了不少星的项目Retrying library for Python,果然还是人家比较有想法,这些重试的逻辑是可以包装为一个库供别人使用的。想到平时自己在写Java代码时,经常还手工写些代码实现重试逻辑,真的挺low的。那么Java里是否有类似的函数库呢?简单搜索了下,发现了两个选择:guava-retrying、 spring-retry。简单比较了下,功能都差不多,但很明显spring-retry更强大一些,支持三种用法:API形式、Annotation形式、XML形式。个
jeremyxu
2018/05/10
1.2K0
聊聊ribbon的retry
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java
code4it
2018/09/17
1.3K0
Spring-Retry 和 Guava-Retry,各有千秋
点击上方蓝色字体,选择“设为星标” 回复”学习资料“获取学习宝典 一 重试框架之Spring-Retry Spring Retry 为 Spring 应用程序提供了声明性重试支持。它用于Spring批处理、Spring集成、Apache Hadoop(等等)。它主要是针对可能抛出异常的一些调用操作,进行有策略的重试 1. Spring-Retry的普通使用方式 1.准备工作 我们只需要加上依赖:  <dependency>     <groupId>org.springframework.retry</
猿天地
2022/08/31
8540
Spring-Retry 和 Guava-Retry,各有千秋
如何在Spring Boot中优雅地重试调用第三方API?
在实际的应用中,我们经常需要调用第三方API来获取数据或执行某些操作。然而,由于网络不稳定、第三方服务异常等原因,API调用可能会失败。为了提高系统的稳定性和可靠性,我们通常会考虑实现重试机制。本文将深入探讨如何在Spring Boot项目中优雅地重试调用第三方API,并结合代码示例,展示具体实现方式。
IT_陈寒
2023/12/14
5970
如何在Spring Boot中优雅地重试调用第三方API?
Spring异常重试框架Spring Retry 重试机制应用
说明(关键总结): 1、使用了@Retryable的方法不能在本类被调用,不然重试机制不会生效。也就是要标记为@Service,然后在其它类使用@Autowired注入或者@Bean去实例才能生效。 关键
oktokeep
2024/10/09
1720
【最佳实践】如何优雅的进行重试
最近公司在搞活动,需要依赖一个第三方接口,测试阶段并没有什么异常状况,但上线后发现依赖的接口有时候会因为内部错误而返回系统异常,虽然概率不大,但总因为这个而报警总是不好的,何况死信队列的消息还需要麻烦运维进行重新投递,所以加上重试机制势在必行。
弗兰克的猫
2019/08/14
1.4K0
使用 @Retryable 注解优雅实现重处理
来源:csdn.net/h254931252/article/details/109257998 目录 前言 @Retryable 是什么? 使用步骤 总结 前言 在实际工作中,重处理是一个非常常见的场景,比如: 发送消息失败。 调用远程服务失败。 争抢锁失败。 这些错误可能是因为网络波动造成的,等待过后重处理就能成功。通常来说,会用 try/catch,while 循环之类的语法来进行重处理,但是这样的做法缺乏统一性,并且不是很方便,要多写很多代码。 然而 spring-retry 却可以通过注解,在不入
程序猿DD
2022/05/05
1.4K0
Retry框架之Spring Retry
分布式系统调用中,经常存在调用超时/异常的情况,因此需要针对超时的情况进行重试处理。
黑洞代码
2021/04/08
5990
相关推荐
初探Spring Retry
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验