当前位置: 首页 > 知识库问答 >
问题:

当远程服务器关闭连接时,Spring Cloud Gateway抛出500错误

邹胜泫
2023-03-14

我实现了自定义GatewayFilterFactory来实现自定义安全性。我观察到网关和远程服务器之间的连接突然关闭时出现间歇性问题。

Spring cloud gateway吞咽异常并向客户端抛出500个内部服务器错误。

完全堆栈跟踪-

java.io.IOException: An existing connection was forcibly closed by the remote host
              at sun.nio.ch.SocketDispatcher.read0(Native Method) ~[na:1.8.0_201]
              at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) ~[na:1.8.0_201]
              at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ~[na:1.8.0_201]
              at sun.nio.ch.IOUtil.read(IOUtil.java:192) ~[na:1.8.0_201]
              at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) ~[na:1.8.0_201]
              at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288) ~[netty-buffer-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) ~[netty-buffer-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:677) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:612) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:529) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:491) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
              at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-common-4.1.33.Final.jar:4.1.33.Final]
              at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_201]

2019-11-21 23:14:26.923 DEBUG [GatewayRoutingService,723236e66f776061,723236e66f776061,false] 18400 --- [ctor-http-nio-2] o.s.c.g.h.RoutePredicateHandlerMapping   : Route matched: grs_rapid_mercht_search_api_node


avax.net.ssl.SSLException: handshake timed out
              at io.netty.handler.ssl.SslHandler.handshake(...)(Unknown Source) ~[netty-handler-4.1.33.Final.jar:4.1.33.Final]

示例实现-

public class MyFilterFactory implements GatewayFilterFactory<JwtService.JwtConfig> {
private static  final  Logger LOGGER = LogManager.getLogger(JwtFilterFactory.class);
public static final String RETRY_ITERATION_KEY = "retry_iteration";

@Override
public GatewayFilter apply(JwtService.JwtConfig config) {

        Predicate<RepeatContext<ServerWebExchange>> repeatPredicate = context -> {
            ServerWebExchange exchange = context.applicationContext();
            if (exceedsMaxIterations(exchange, config)) {
                return false;
            }

            HttpStatus statusCode = exchange.getResponse().getStatusCode();
            return config.getUnAuthStatusCode().equals(statusCode)|| statusCode.is5xxServerError();
        };

    Repeat<ServerWebExchange>  statusCodeRepeat = Repeat.onlyIf(repeatPredicate)
                .doOnRepeat(context -> reset(context.applicationContext()));

    return (exchange, chain) -> {

        Publisher<Void> publisher = chain.filter(exchange.mutate().request(
                exchange.getRequest().mutate().
                        //Populate Request header
                                header(HttpHeaders.AUTHORIZATION,jwtTokenFormatted)
                        .build()).build())
                .doOnSuccessOrError((aVoid, throwable) -> {
                    int iteration = exchange
                            .getAttributeOrDefault(RETRY_ITERATION_KEY, -1);
                    int newIteration = iteration + 1;

                    exchange.getAttributes().put(RETRY_ITERATION_KEY, newIteration);
                });

        if (statusCodeRepeat != null) {
            publisher = ((Mono<Void>) publisher)
                    .repeatWhen(statusCodeRepeat.withApplicationContext(exchange));
        }

        return Mono.fromDirect(publisher);
    };

}

public boolean exceedsMaxIterations(ServerWebExchange exchange,
                                    JwtService.JwtConfig retryConfig) {
    Integer iteration = exchange.getAttribute(RETRY_ITERATION_KEY);
    // TODO: deal with null iteration
    boolean exceeds = iteration != null && iteration >= retryConfig.getRetries();
    LOGGER.trace("exceedsMaxIterations %b, iteration %d, configured retries %d", exceeds,
            iteration, retryConfig.getRetries());
    return exceeds;
}


public void reset(ServerWebExchange exchange) {
    LOGGER.debug("Inside reset method :{} ",exchange.getRequest().getHeaders());
    Set<String> addedHeaders = exchange.getAttributeOrDefault(
            CLIENT_RESPONSE_HEADER_NAMES, Collections.emptySet());
    addedHeaders
            .forEach(header -> exchange.getResponse().getHeaders().remove(header));
    exchange.getAttributes().remove(GATEWAY_ALREADY_ROUTED_ATTR);

}
}

以下查询的任何建议-

  • 如何确保netty将连接/握手错误转发到客户端,而不是抛出500个内部服务器错误?
  • 如何重新建立关闭的连接?

共有1个答案

贡英华
2023-03-14

可能是spring.cloud.gateway.loadbalancer。use404=true在这里很有用。

 类似资料:
  • 错误:传输错误202:绑定失败:地址已在使用错误:JDWP传输dt_socket初始化失败,TRANSPORT_INIT(510)JDWP退出错误AGENT_ERROR_TRANSPORT_INIT(197):未初始化传输[debuginit.c:750]本机方法中的致命错误:JDWP未初始化传输,jvmtierror=AGENT_ERROR_TRANSPORT_INIT(197) 知道吗?

  • 删除php扩展URL。//.htAccess代码 RewriteEngine on RewiteRule^dashboard$dashboard.php[L] 内部服务器错误服务器遇到内部错误或配置错误,无法完成您的请求。 请与postmaster@localhost的服务器管理员联系,通知他们此错误发生的时间,以及您在此错误发生之前执行的操作。 有关此错误的详细信息可以在服务器错误日志中获得。

  • Netty服务器,Fedora。我只是无法从远程主机连接到服务器,并且通过util没有显示监听套接字。但是我可以在同一台机器上建立运行客户端和服务器的连接。就像这样: 我已尝试仅使用端口、localhost IP、0.0.0.0 IP和网络IP初始化

  • 问题内容: 关闭。 此问题不符合堆栈溢出准则。它当前不接受答案。 想改善这个问题吗? 更新问题,使其成为Stack Overflow的主题。 2年前关闭。 改善这个问题 我想在我可以访问的计算机上运行服务器,并且已经能够在本地运行笔记本计算机。 如何设置以便可以 远程 访问? 问题答案: 如果您具有ssh访问将运行服务器的计算机的权限,请执行以下步骤: 1)在将运行 服务器 的机器上,执行: 2)

  • 每个人我需要使用服务器和客户端证书连接到服务器。我正在使用以下代码:(移植形式的android) 我已为ssl和握手启用调试属性,并获得以下输出: 我得到这个错误在Android设备和桌面java。但是我可以使用这个客户端证书自由地用网络浏览器连接到服务器。 也许这是重要的或不Url的服务器是:https://icon.sbrf.ru:9443(注意端口)也客户端证书是与西里尔名称(我不知道是这件

  • 我正在使用mybatis连接到Oracle。 我的mybatis配置是: 我的开放会话代码就像 由于类的应用范围,而sqlSession不能在应用范围内使用,所以我必须自己管理sqlSession。 2019-04-11 15:30:41,861信息[stdout](默认任务-57)声称连接过期962608913。 2019-04-11 15:30:41,861信息[stdout](默认任务-57