[http-nio-28688-exec-5] [com.gaotu.course.center.webcommon.handler.GlobalExcepti...
错误信息
2026-01-04 09:53:07.038 ERROR [http-nio-28688-exec-5] [com.gaotu.course.center.webcommon.handler.GlobalExceptionHandler.exceptionHandler:76] ce6ff49829b0eaefd892f646288c3010 - [TID: e23154f8-3b1c-4a57-9b9b-6bcd3f06f6ff.0.3] 请求处理异常,url:[http://test-mi.gaotu100.com/b/teachClazz/search], params:[requestBody={"arrangeModeTypeList":[4],"arrangeStatus":1,"pager":{"current":1,"pageSize":10,"pageNum":1}}]
com.netflix.hystrix.exception.HystrixRuntimeException: ClazzTypeFeignClient#listAllByClazzTypeNumberList(ClazzTypeRequest) failed and no fallback available.
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:819)
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:804)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1472)
at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1397)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:142)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.onError(AbstractCommand.java:1194)
at rx.internal.operators.OperatorSubscribeOn$1$1.onError(OperatorSubscribeOn.java:59)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at com.netflix.hystrix.AbstractCommand$DeprecatedOnRunHookApplication$1.onError(AbstractCommand.java:1431)
at com.netflix.hystrix.AbstractCommand$ExecutionHookApplication$1.onError(AbstractCommand.java:1362)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
at com.baijia.gapm.apm.plugin.hystrix.v1.SWHystrixConcurrencyStrategyWrapper$WrappedCallable.call(SWHystrixConcurrencyStrategyWrapper.java:57)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Caused by: feign.codec.DecodeException: field null expect '[', but {, pos 1, line 1, column 2{"code":500,"success":false,"msg":"系统异常,请稍后重试","stackMessage":""}
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:169)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:133)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at feign.hystrix.HystrixInvocationHandler$1.run$original$a2LxnmiX(HystrixInvocationHandler.java:108)
at feign.hystrix.HystrixInvocationHandler$1.run$original$a2LxnmiX$accessor$Mhn1DSWz(HystrixInvocationHandler.java)
at feign.hystrix.HystrixInvocationHandler$1$auxiliary$OU51SbMH.call(Unknown Source)
at com.baijia.gapm.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:92)
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
... 27 more
Caused by: com.alibaba.fastjson.JSONException: field null expect '[', but {, pos 1, line 1, column 2{"code":500,"success":false,"msg":"系统异常,请稍后重试","stackMessage":""}
at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:738)
at com.alibaba.fastjson.serializer.CollectionCodec.deserialze(CollectionCodec.java:132)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:705)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:394)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:476)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:584)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:551)
at com.gaotu.ces.teach.product.api.configration.CesTeachProductFastJsonFeignConfig$CustomDecoder.decode(CesTeachProductFastJsonFeignConfig.java:46)
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:165)
... 37 more
AI 解决方案
Hystrix + Feign JSON 反序列化错误分析
1. 错误翻译
原文:
com.netflix.hystrix.exception.HystrixRuntimeException: ClazzTypeFeignClient#listAllByClazzTypeNumberList(ClazzTypeRequest) failed and no fallback available.
译文:
ClazzTypeFeignClient 的 listAllByClazzTypeNumberList 方法调用失败,且没有可用的降级处理机制。
原文:
com.alibaba.fastjson.JSONException: field null expect '[', but {, pos 1, line 1, column 2
译文:
FastJSON 解析异常:期望字段是数组(以 '[' 开头),但实际接收到的是对象(以 '{' 开头),位置在第1行第2列。
2. 原因分析
根本原因
错误位置
ClazzTypeFeignClient#listAllByClazzTypeNumberList(ClazzTypeRequest){ 字符,说明返回的是对象(如 {"code":500,...}),而不是数组3. 解决方案
方案一:修复 Feign Client 接口定义(推荐)
// 原接口(期望返回 List)
@FeignClient(name = "clazz-type-service")
public interface ClazzTypeFeignClient {
@PostMapping("/api/clazz-type/list")
List<ClazzType> listAllByClazzTypeNumberList(@RequestBody ClazzTypeRequest request);
}
// 修复为:返回统一响应对象
@FeignClient(name = "clazz-type-service")
public interface ClazzTypeFeignClient {
@PostMapping("/api/clazz-type/list")
ResponseWrapper<List<ClazzType>> listAllByClazzTypeNumberList(@RequestBody ClazzTypeRequest request);
}
// 响应包装类
@Data
public class ResponseWrapper<T> {
private Integer code;
private Boolean success;
private String msg;
private T data; // 实际数据
private String stackMessage;
}
方案二:自定义 Feign Decoder 处理响应
// 1. 创建自定义解码器
@Component
public class CustomFastJsonDecoder implements Decoder {
@Override
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
// 先解析为 ResponseWrapper
ResponseWrapper<?> wrapper = JSON.parseObject(bodyStr, ResponseWrapper.class);
// 检查响应状态
if (!wrapper.getSuccess()) {
throw new RuntimeException("远程服务异常: " + wrapper.getMsg());
}
// 提取实际数据部分进行反序列化
String dataJson = JSON.toJSONString(wrapper.getData());
return JSON.parseObject(dataJson, type);
}
}
// 2. 在 Feign Client 配置中使用自定义解码器
@FeignClient(
name = "clazz-type-service",
configuration = CustomFeignConfig.class
)
public interface ClazzTypeFeignClient {
// ...
}
方案三:添加 Hystrix 降级策略
@FeignClient(
name = "clazz-type-service",
fallback = ClazzTypeFeignClientFallback.class
)
public interface ClazzTypeFeignClient {
@PostMapping("/api/clazz-type/list")
ResponseWrapper<List<ClazzType>> listAllByClazzTypeNumberList(@RequestBody ClazzTypeRequest request);
}
// 降级实现
@Component
public class ClazzTypeFeignClientFallback implements ClazzTypeFeignClient {
@Override
public ResponseWrapper<List<ClazzType>> listAllByClazzTypeNumberList(ClazzTypeRequest request) {
// 返回默认值或空列表,避免级联故障
ResponseWrapper<List<ClazzType>> wrapper = new ResponseWrapper<>();
wrapper.setCode(200);
wrapper.setSuccess(true);
wrapper.setMsg("服务降级返回");
wrapper.setData(Collections.emptyList());
return wrapper;
}
}
4. ️ 预防措施
️ 最佳实践建议
- 所有 Feign 接口统一使用
ResponseWrapper<T> 包装响应- 避免直接返回
List<T> 或基础类型- 完善的降级机制:
# application.yml 配置
feign:
hystrix:
enabled: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
circuitBreaker:
requestVolumeThreshold: 20
sleepWindowInMilliseconds: 5000
开发工具推荐
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}