java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringCloud Gateway采用OpenFeign远程调用失败

解决SpringCloud Gateway采用OpenFeign远程调用失败的问题

作者:Ramboooooooo

在使用SpringCloud网关进行统一鉴权和认证过程中,通过OpenFeign远程调用鉴权服务器接口时可能会遇到远程调用失败的问题,这通常是因为HttpMessageConverters没有被正确注入到Spring容器中

一、框架版本

Spring Boot、 Spring Cloud 、 Spring Cloud Alibaba

框架名称框架版本
Spring Boot2.2.5.RELEASE
Spring CloudHoxton.SR3
Spring Cloud Alibaba2.2.1.RELEASE

二、源码展示

远程鉴权 Controller 控制器代码片段

@RestController
@Slf4j
@RequestMapping("/security")
public class AuthenticationController {

    @Resource
    private AuthenticationService authenticationService;

    @PostMapping("/auth")
    public Boolean checkAuth(@RequestBody @Valid BaseRequest baseRequest) {
        log.info("<-------------------------->");
        return authenticationService.checkAuth(baseRequest);
    }
}

网关引用 OpenFeign 依赖

<!-- OpenFeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>

网关 OpenFeign 调用客户端

@Component
@FeignClient(value = "rms-security-service")
public interface InvokeSecurityServiceClient {

    @PostMapping("/security/auth")
    Boolean checkAuth(BaseRequest baseRequest);
}

三、问题描述

在网关层进行统一鉴权和认证的过程中,需要远程调用鉴权服务器的接口进行鉴权的操作。

但是在采用 OpenFiegn 进行远程调用的过程中,出现了如下的报错堆栈,导致了远程调用失败

feign.codec.EncodeException: No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:384)
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ cn.com.jstec.open.cloud.gateway.config.SecurityConfig$$Lambda$772/0x0000016c006c3040 [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP GET "/open-platform/achievement/list?page=1" [ExceptionHandlingWebHandler]
Stack trace:

No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters

四、解决方案

堆栈分析

解决方案

源码:HttpMessageConverters.java 中没有发现异常,于是开始查看是否存在 AutoConfiguration 打开 HttpMessageConvertersAutoConfiguration.java

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HttpMessageConverter.class)
@Conditional(NotReactiveWebApplicationCondition.class)
@AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class })
@Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class,
		JsonbHttpMessageConvertersConfiguration.class })
public class HttpMessageConvertersAutoConfiguration {
}

源码:@Conditional(NotReactiveWebApplicationCondition.class) @ConditionalSpring4 新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册 bean 再查看类 NotReactiveWebApplicationCondition

static class NotReactiveWebApplicationCondition extends NoneNestedConditions {

		NotReactiveWebApplicationCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}

		@ConditionalOnWebApplication(type = Type.REACTIVE)
		private static class ReactiveWebApplication {

		}

	}

Spring Cloud Gateway 是基于 WebFlux 的,是 ReactiveWeb,所以 HttpMessageConverters 不会自动注入。

于是自己在配置文件中,直接复制源码的 Bean,最终成功。

# 新建配置类
@Configuration
public class WebFluxWithOpenFeignConfig {
    @Bean
    @ConditionalOnMissingBean
    public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
        return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文