我有一个非常简单的spring-cloud-gateway和一个过滤器(它扩展了AbstractGatewayFilterFactory)。
在过滤器内部,我使用Spring的RestTemplate进行REST API调用。rest调用只工作一次,但是来自过滤器的每个后续调用都会挂起,并且响应永远不会返回给客户端。我启用了日志记录来跟踪,但当REST调用挂起时,日志中没有任何内容。
我从@spencergibb的一个评论here中了解到,任何阻塞SCG主线程的东西都是从根本上被破坏的。但在将请求转发到下游服务之前,我需要此API调用确实处于阻塞状态。
下面是我的过滤器实现(裁剪关闭):
@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 {
}
}发布于 2019-08-26 13:01:44
请不要在调用restTemplate之前读取(通过读取的方式记录)请求正文。spring云网关需要记录请求体的内容,但请求体只能读一次。如果读取后没有封装请求body,则后一个服务将无法读取body数据。follow this
发布于 2020-12-23 23:05:19
我认为从GatewayFilter调用另一个服务的推荐方式是请求链。
例如,为了对每个过滤的请求调用google:
@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。
https://stackoverflow.com/questions/57544229
复制相似问题