当前位置: 首页 > news >正文

Feign 调用为服务报 `HardCodedTarget(type=xxxClient, name=xxxfile, url=http://file)`异常

Feign 调用为服务报 HardCodedTarget(type=xxxClient, name=xxxfile, url=http://file)异常

前言

业务场景如下:
1,本项目需要新增文案数据,文案可以绑定文件,比如【文档类:xls txt ppt word pdf … 图片类:jpg jpeg jif … 音频类:mp3 mp4 avi …】
2,文件上传保存的服务是在另一个服务 我们这里取名叫 smart_app_file 为服务

代码如下

线程池的配置如下:

package com.xx.xx.config;import lombok.Data;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskDecorator;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** @author psd*/
@Data
@Configuration
public class ThreadPoolConfig {@Value("${threadPool.coreSize}")Integer coreSize;@Value("${threadPool.maxSize}")Integer maxSize;@Value("${threadPool.keepLiveTime}")Integer keepLiveTime;@Value("${threadPool.blockQueueSize}")Integer blockQueueSize;@Beanpublic ThreadPoolExecutor threadPoolExecutor() {return new ThreadPoolExecutor(coreSize, maxSize, keepLiveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>(blockQueueSize));}
}

业务代码异步

    @ApiOperation("根据dto新增文案的数据")@PostMapping("/insertxxxxPlan")public Long insertxxxxPlan(@Validated @RequestBody PlanDto dto) {return cxxxPlanService.insertxxxxPlan(dto);}
@Override@Transactional(rollbackFor = Exception.class)public Long insertContingencyPlan(ContingencyPlanDto dto) {// 1.业务代码... // 4.修改smart_app_file中文件列表 应用个数+1. 【这里是调用smartAppFile微服务】int addRefCount = smartAppFileClient.batchAddRefCount(flIds);log.info("调用 smart_app_file 修改应用个数影响的行数有:{}", addRefCount);// 5.异步添加索引到ESCompletableFuture.runAsync(() -> {log.info("应急预案开始异步:{} , {}",planEntity , flIds);contingxxxPlanEsService.indexCxxxPlan(planEntity, flIds);}, threadCustomPoolExecutor);return planEntity.getId();}

调用远程服务的代码如下

@Overridepublic void indexCxxxPlan(ContingencyPlanEntity planEntity, Set<Long> flIds) {try {log.info("smartAppFileClient 获取的数据是:{}",smartFileClient);// 1.获取文件信息R<List<FileListEntity>> fileListEntitiesr = smartAppFileClient.queryFileListByIds(flIds);log.info("fileListEntitiesr 返回的数据是:{} " , fileListEntitiesr);List<FileListEntity> fileListEntities = fileListEntitiesr.getData();......// 3.构建ES文档...// 4.索引到ES// 新增文档 - 请求对象IndexRequest indexRequest = new IndexRequest("contingency_app_plans").id(planEntity.getId().toString());// 添加文档数据,数据转换为JsonString contxxxEsDocJson = objectMapper.writeValueAsString(esDocument);indexRequest.source(contxxxEsDocJson,  XContentType.JSON);IndexResponse response = esClient.index(indexRequest, RequestOptions.DEFAULT);log.info("新增的应急xxx的ES的结果是:{} , id是:{}", response.getResult(), response.getId());} catch (IOException e) {log.error("新增应急xxx的ES失败,应急xxx的id是:{} ", planEntity.getId(), e);}}

Feign 的代码如下


package com.xxx.xxx.service.feign;import com.xxx;
import com.xxxo.xxx.common.web.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;import java.util.List;
import java.util.Set;/*** @author psd 调用 smart_app_file 模块的接口*/
@FeignClient("file")
public interface SmartAppFileClient {/*** 根据ids查询文件列表集合** @param ids*            文件id* @return List<FileListEntity>*/@PostMapping("/file/queryFileListByIds")public R<List<FileListEntity>> queryFileListByIds(@RequestBody Set<Long> ids);

打印日志报
INFO com.xx.nx x x.service.impl.ContingencyAppPlanEsServiceImpl - smartFileClient 获取的数据是:HardCodedTarget(type=SmartAppFileClient, name=file, url=http://file)
2025-08-26 18:52:52.910 [http-nio-16710-exec-3] INFO

问题解析是:
可能的原因:

  1. Feign客户端调用失败,但没有抛出异常(因为被捕获了?),但是查看代码,在indexContingencyPlan方法中捕获的是IOException,而Feign调用可能抛出的是FeignException,属于RuntimeException,所以没有被捕获,但奇怪的是也没有看到异常日志。
  2. 线程上下文问题:Feign调用通常依赖于Spring的上下文(如请求拦截器、负载均衡等),而在异步线程中,可能无法获取到正确的上下文,导致Feign调用失败。
    但是,从日志中看到,在异步线程中打印了smartAppFileClient对象,说明该对象不是null,而且Feign客户端已经正常创建。
    另外,注意到在异步线程打印日志的同时,主线程(http-nio-16710-exec-3)打印了AuthInterceptor的后置处理日志。这提示我们可能异步线程中缺少了某些上下文,例如安全上下文、请求头等,导致Feign调用时没有正确的认证信息。
    解决方案:
  3. 确保Feign调用能够传递必要的请求头(如认证信息)。可以使用Feign的拦截器,或者自定义请求拦截器,在异步线程中手动设置请求头。
  4. 检查异步线程的线程池配置,是否支持上下文传播。如果你使用的是Spring Boot 3.x,可以考虑使用Spring Boot的异步支持并配置任务装饰器(TaskDecorator)来传递上下文。如果是较低版本,可以考虑使用其他方式(如InheritableThreadLocal)或者手动传递上下文。
    但是,从代码中看到,你使用了自定义的线程池threadCustomPoolExecutor,那么需要确保这个线程池配置了上下文传播。

解决思路

1.添加maven依赖
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId>
</dependency>
2. 手动传递上下文到异步线程
@Override
@Transactional(rollbackFor = Exception.class)
public Long insertxxxContingencyPlan(ContingencyxxxPlanDto dto) {// ... [原有代码] ...// 捕获当前请求上下文和安全上下文RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();SecurityContext securityContext = SecurityContextHolder.getContext();// 5.异步添加索引到ESCompletableFuture.runAsync(() -> {try {// 恢复上下文到异步线程RequestContextHolder.setRequestAttributes(requestAttributes);SecurityContextHolder.setContext(securityContext);log.info("xxxx开始异步:{} , {}", planEntity, flIds);contingencyPlanEsService.indexContingencyPlan(planEntity, flIds);} finally {// 清理上下文避免内存泄漏RequestContextHolder.resetRequestAttributes();SecurityContextHolder.clearContext();}}, threadCustomPoolExecutor);return planEntity.getId();
}
3. 配置线程池支持上下文传递

如果使用自定义线程池(threadCustomPoolExecutor),需确保其支持上下文传播。推荐使用 TaskDecorator:

@Override
@Transactional(rollbackFor = Exception.class)
public Long insertContingencyPlan(ContingencyPlanDto dto) {// ... [原有代码] ...// 捕获当前请求上下文和安全上下文RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();SecurityContext securityContext = SecurityContextHolder.getContext();// 5.异步添加索引到ESCompletableFuture.runAsync(() -> {try {// 恢复上下文到异步线程RequestContextHolder.setRequestAttributes(requestAttributes);SecurityContextHolder.setContext(securityContext);log.info("应急预案开始异步:{} , {}", planEntity, flIds);contingencyPlanEsService.indexContingencyPlan(planEntity, flIds);} finally {// 清理上下文避免内存泄漏RequestContextHolder.resetRequestAttributes();SecurityContextHolder.clearContext();}}, threadCustomPoolExecutor);return planEntity.getId();
}

总结:

1,异步调用smartAppFile 开始时候没有传上下文的参数,一般情况下会被拦截掉
2,本地测试时候当时是直接多数据源调用数据库查询的数据,发到测试环境是走的微服务调用
3,异常没有捕获到,这个也是一个误区。

http://www.dtcms.com/a/351683.html

相关文章:

  • 关于C#中运算符的简单说明
  • 为什么的中小企业很难承受“大型系统”的成本
  • 【RAGFlow代码详解-10】文本处理和查询处理
  • 深度学习(五):正则化:约束模型的复杂度
  • 什么样的 IP 能穿越周期,持续被用户买单?​
  • 深入解析交换机端口安全:Sticky MAC的工作原理与应用实践
  • 自动化测试概念与 Web 自动化实战(基于 Selenium)
  • 第一篇:MySQL安装部署全攻略
  • 计算机毕业设计 java 养老院管理系统 基于 Java 的养老院管理平台 Java 开发的养老服务系统
  • Linux云计算运维简明教程02 应用运维
  • 视频合成素材视频-多合一功能-青柠剪吧
  • 智能手机使用(2015-2019)
  • 基于MATLAB的运动模糊图像修复方法研究(LW+源码+讲解+部署)
  • vue2+elementui 表格单元格增加背景色,根据每列数据的大小 颜色依次变浅显示
  • 科研笔记:SCI论文中的功能性图表
  • 【技术教程】如何将文档编辑器集成到用 .Net 编写的网络应用程序中
  • VScode,设置自动保存
  • 支持向量机学习
  • Ubuntu22.04 安装和使用标注工具labelImg
  • GZ-CTF平台pwn题目部署
  • GitHub 热榜项目 - 日榜(2025-08-26)
  • word批量修改交叉引用颜色
  • 【RAGFlow代码详解-28】部署和基础设施
  • 国标28181 国标视频平台
  • 四、Python 脚本常用模块(续)
  • Linux虚拟机ansible部署
  • 机器视觉学习-day04-形态学变换
  • Spring Boot 与传统 Spring:从 WAR 到可执行 JAR,颠覆性的部署哲学
  • MEMS陀螺定向短节与传统陀螺工具的区别?
  • 永磁同步电机无速度算法--传统脉振方波注入法(1)