Netflix Eureka微服务调用异常:Service2调用Service1遇401及500错误
这问题我之前在项目里碰到过,一眼就看出核心问题是Feign调用时身份认证信息没传递到位——Service2调用Service1的getUserByUsername接口时,没携带Service1要求的认证凭证,被Service1拒绝访问返回401,而Service2没处理这个Feign调用异常,直接抛出导致了500内部错误。
先把报错核心信息拎出来:
发生了意外错误(类型=内部服务器错误,状态=500)。读取UserFeignClient#getUserByUsername(String)时状态码401
feign.FeignException: status 401 reading UserFeignClient#getUserByUsername(String)
简单说就是:Service1要求身份认证,但Service2的Feign调用没带凭证→Service1返回401→Service2未捕获该异常→触发500错误。
根据不同的认证场景,给你几个常用的解决办法:
场景一:JWT/Token类认证(最常见)
如果系统用的是请求头带Token的认证方式,需要把Service2当前收到的请求里的Token,自动传递给Feign调用的请求。可以写个Feign拦截器实现:@Component public class FeignTokenInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 拿到当前请求的上下文 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); // 从请求头取Token(这里假设Token存在Authorization头里) String token = request.getHeader("Authorization"); if (token != null) { // 把Token放到Feign调用的请求头中 template.header("Authorization", token); } } } }这样每次Feign调用都会自动带上当前请求的Token,Service1就能正常校验身份了。
场景二:Basic基础认证
如果Service1用的是Basic认证,直接在Feign客户端配置用户名密码就行:@FeignClient(name = "service1", configuration = FeignBasicAuthConfig.class) public interface UserFeignClient { @GetMapping("/user/{username}") User getUserByUsername(@PathVariable("username") String username); } // 单独的Basic认证配置类 class FeignBasicAuthConfig { @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("你的用户名", "你的密码"); } }场景三:全局处理Feign异常(避免直接返回500)
就算认证信息传对了,也可能有其他情况导致401,这时候可以自定义Feign的错误解码器,把401异常转换成更友好的提示,而不是直接抛出500:@Component public class CustomFeignErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { if (response.status() == 401) { return new RuntimeException("调用Service1未授权,请检查认证凭证是否有效"); } // 其他状态码按默认逻辑处理 return FeignException.errorStatus(methodKey, response); } }
- 确认Service1的认证规则是否正确,比如Token过期时间、Basic认证的用户名密码是否匹配
- 检查Service2和Service1之间有没有网关、代理拦截了请求头,导致Token没传过去
- 如果用了Spring Cloud,确认Feign的熔断配置(比如
feign.hystrix.enabled)是否影响了请求的正常传递
内容的提问来源于stack exchange,提问作者Esaimozhi Mezhivalavan

