在CompletableFuture.runAsync()中使用 openFeign进行远程调用时报错

基于架构

  • Spring Cloud(微服务)
  • Eureka(服务注册与发现)
  • openFeign(远程调用)

问题出现

今天在使用CompletableFuture.runAsync()进行异步处理的情况下,在其内部的方法中有进行了服务之间的RPC远程调用,发生了报错,报错信息如下:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.springframework.cloud.netflix.eureka.loadbalancer.EurekaLoadBalancerClientConfiguration]
2023-11-20T08:00:06.347980398Z 	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:178) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.347983603Z 	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:398) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.347986734Z 	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:283) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.348002958Z 	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.348007361Z 	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.348010447Z 	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:745) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.348013338Z 	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:565) ~[spring-context-6.0.4.jar!/:6.0.4]
2023-11-20T08:00:06.348016094Z 	at org.springframework.cloud.context.named.NamedContextFactory.createContext(NamedContextFactory.java:138) ~[spring-cloud-context-4.0.1.jar!/:4.0.1]
2023-11-20T08:00:06.348018664Z 	at org.springframework.cloud.context.named.NamedContextFactory.getContext(NamedContextFactory.java:122) ~[spring-cloud-context-4.0.1.jar!/:4.0.1]
2023-11-20T08:00:06.348022604Z 	at org.springframework.cloud.context.named.NamedContextFactory.getInstances(NamedContextFactory.java:236) ~[spring-cloud-context-4.0.1.jar!/:4.0.1]
2023-11-20T08:00:06.348025371Z 	at org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient.lambda$execute$2(RetryableFeignBlockingLoadBalancerClient.java:140) ~[spring-cloud-openfeign-core-4.0.1.jar!/:4.0.1]
2023-11-20T08:00:06.348028358Z 	at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329) ~[spring-retry-2.0.0.jar!/:na]
2023-11-20T08:00:06.348030959Z 	at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225) ~[spring-retry-2.0.0.jar!/:na]
2023-11-20T08:00:06.348033453Z 	at org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient.execute(RetryableFeignBlockingLoadBalancerClient.java:135) ~[spring-cloud-openfeign-core-4.0.1.jar!/:4.0.1]

我的代码如下:

// 异步处理
CompletableFuture.runAsync(() -> asyncHandleImportAvatarAndPush(tempFile));

解决方法

注意:若出现这个问题,则必须配置自定义线程池!!!
例如:

// 其中asyncHandleImportAvatarAndPush为你需要处理的方法
CompletableFuture.runAsync(() -> asyncHandleImportAvatarAndPush(tempFile), taskExecutor);

这里给出我这边自定义线程池类供参考:

/**
 * @Author: ou_sir
 * @Description: 自定义线程池配置
 * @Date: 2023/07/26
 */
@Slf4j
@Configuration
@EnableAsync
@EnableScheduling
public class TaskExecutorConfig implements SchedulingConfigurer, AsyncConfigurer {

    // 线程池核心线程数
    private static final int CORE_POOL_SIZE = 20;
    // 线程池最大线程数
    private static final int MAX_POOL_SIZE = 50;
    // 线程池队列容量
    private static final int QUEUE_CAPACITY = 99999;

    /**
     * 异步任务使用的线程池
     *
     * @return
     */
    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 配置核心线程数
        taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        // 配置最大线程数
        taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        // 配置队列大小
        taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        // 配置线程池中的线程的名称前缀
        taskExecutor.setThreadNamePrefix("XXX-taskExecutor-");
        // 线程池拒绝策略:当线程池队列已满时,新提交的任务由调用者所在的线程来执行
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有线程结束之后关闭线程池
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 执行初始化
        taskExecutor.initialize();
        return taskExecutor;
    }

    /**
     * 定时任务使用的线程池
     *
     * @return
     */
    @Bean(destroyMethod = "shutdown", name = "taskScheduler")
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("XXX-taskScheduler-");
        scheduler.setAwaitTerminationSeconds(600);
        scheduler.setWaitForTasksToCompleteOnShutdown(false);
        return scheduler;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = taskScheduler();
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
    }

    @Override
    public Executor getAsyncExecutor() {
        return taskExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("异步任务执行出现异常, message {}, method {}, params {}", throwable, method, objects);
        };
    }
}

参考文章

https://blog.csdn.net/tergou/article/details/131400864

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值