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

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,添加线程的上下文传播
2,组装可以上下文传播的线程池
3,异步调用获取上下文传递上下文

步骤如下:

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.xdnf.cn/news/18882.html

相关文章:

  • 大模型入门实战 | 基于 YOLO 数据集微调 Qwen2.5-VL-3B-Instruct 的目标检测任务
  • YggJS RButton 按钮组件 v1.0.0 使用教程
  • 【vue eslint】报错:Component name “xxxx“ should always be multi-word
  • 云上“安全管家”|移动云以云安全中心为企业数字化升级保驾护航
  • 科技信息差(8.26)
  • 【软考论文】论静态测试方法及其应用
  • PortSwigger靶场之Blind SQL injection with out-of-band interaction通关秘籍
  • 软考-系统架构设计师 计算机系统基础知识详细讲解
  • 【46页PPT】AI智能中台用ABC+IOT重新定义制造(附下载方式)
  • 相机Camera日志实例分析之十五:相机Camx【照片后置HDR拍照】单帧流程日志详解
  • 2-5 倍性能提升,30% 成本降低,阿里云 SelectDB 存算分离架构助力波司登集团实现降本增效
  • 支持向量机核心知识总结
  • Java大厂面试实战:从Spring Boot到微服务架构的深度剖析
  • 宠物智能,是「养宠自由」还是「焦虑税」?
  • 【分享开题答辩过程】一辆摩托车带来的通关副本攻略----《摩托车网上销售系统》开题答辩!!
  • Stream流中的Map与flatMap的区别
  • AI安全监控与人才需求的时间悖论(对AI安全模型、AI安全人才需求的一些思考)
  • 前沿技术借鉴研讨-2025.8.26(多任务分类/预测)
  • 基于CentOS7:Linux服务器的初始化流程
  • 从零开始学MCP(7) | 实战:用 MCP 构建论文分析智能体
  • Java 大视界 -- Java 大数据机器学习模型在金融市场波动预测与资产配置动态调整中的应用
  • Docker:部署Java后端
  • 【笔记】大模型业务场景流程综述
  • Text to Speech技术详解与实战:GPT-4o Mini TTS API应用指南
  • 大数据毕业设计选题:基于大数据的用户贷款行为数据分析系统Spark SQL核心技术
  • SQL server 触发器的使用
  • defineCustomElement 的局限性及重载需求分析
  • Ubuntu 虚拟机配置 Git 并推送到Gitee
  • 如何利用Claude在商业项目中进行自动化客户反馈分析:一站式解决方案
  • 【R代码分析】甲烷排放绘制代码-参考论文