首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自spring-cloud-gateway筛选器的RestTemplate调用挂起

来自spring-cloud-gateway筛选器的RestTemplate调用挂起
EN

Stack Overflow用户
提问于 2019-08-18 19:45:43
回答 2查看 2.1K关注 0票数 1

我有一个非常简单的spring-cloud-gateway和一个过滤器(它扩展了AbstractGatewayFilterFactory)。

在过滤器内部,我使用Spring的RestTemplate进行REST API调用。rest调用只工作一次,但是来自过滤器的每个后续调用都会挂起,并且响应永远不会返回给客户端。我启用了日志记录来跟踪,但当REST调用挂起时,日志中没有任何内容。

我从@spencergibb的一个评论here中了解到,任何阻塞SCG主线程的东西都是从根本上被破坏的。但在将请求转发到下游服务之前,我需要此API调用确实处于阻塞状态。

下面是我的过滤器实现(裁剪关闭):

代码语言:javascript
复制
@Component
public class ApiRequestHeaderFilter extends AbstractGatewayFilterFactory<ApiRequestHeaderFilter.Config> {

    private static RestTemplate restTemplate = new RestTemplate();

    public ApiRequestHeaderFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String someHeaderValue = Objects.requireNonNull(request.getHeaders().get("SOME_HEADER")).get(0);
            callRestApi();

            return chain.filter(exchange);
        };
    }

    private void callRestApi() {

        UriComponentsBuilder uriBuilder = .... //build the API URL

        final ResponseEntity<List<MyCustomObject>> response = restTemplate.exchange(uriBuilder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference<List<MyCustomObject>>() {
        });

        ....  //process the response
        ....  
    }

    static class Config {
    }
}
EN

回答 2

Stack Overflow用户

发布于 2019-08-26 13:01:44

请不要在调用restTemplate之前读取(通过读取的方式记录)请求正文。spring云网关需要记录请求体的内容,但请求体只能读一次。如果读取后没有封装请求body,则后一个服务将无法读取body数据。follow this

票数 0
EN

Stack Overflow用户

发布于 2020-12-23 23:05:19

我认为从GatewayFilter调用另一个服务的推荐方式是请求链。

例如,为了对每个过滤的请求调用google:

代码语言:javascript
复制
@Override
public GatewayFilter apply(Config config) {
    return (exchange, chain) -> WebClient.create("https://www.google.com")
            .method(HttpMethod.GET)
            .retrieve()
            .bodyToMono(String.class)
            .map(s -> {
                System.out.println(s);
                return exchange;
            })
            .flatMap(chain::filter);
}

在本例中,使用了WebClient,它是一个与RestTemplate不同的非阻塞客户端。

bodyToMono方法生成的Mono可以在执行必要的操作后映射到exchange,以便继续进行过滤。

有关详细信息,请参阅this great baeldung guide

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57544229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档