簡體   English   中英

通過 AWS Nat 網關的連接問題

[英]Connection issues through AWS Nat Gateway

我有一個 Amazon Linux 2 應用程序服務器,在私有 su.net 中帶有 Spring Boot 應用程序。 公共su.net中那個應用服務器前面有一個Nat網關。 應用程序發送一個連接請求:keep-alive header 到遠程主機,遠程主機用相同的 header 發回響應。所以我可以通過 .netstat 看到已建立的連接。

netstat -t | grep <remote server ip>
tcp6       0      0 ip-172-30-4-31.eu:57324 <remote server ip>:http       ESTABLISHED

由於 350 秒內沒有流量,Nat 網關根據本文檔關閉連接: https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-troubleshooting.html#nat-gateway-troubleshooting-timeout但連接仍在應用程序服務器上 Established state,所以對遠程服務器的下一個請求給我:

java.net.SocketException: Connection reset

我試圖在sysctl.conf中的應用程序服務器上進行更改,以幾乎同時關閉與 Nat 網關的連接:

net.ipv4.tcp_keepalive_time=351
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=2

但是沒有任何反應,通過 tcpdump 從應用程序服務器向遠程服務器轉儲流量沒有給我任何保持活動的數據包。 那么除了在我的應用程序中刪除 Connection header 之外,我還能做些什么來避免這個問題呢?

問題是因為用於打開套接字的方法。 我用過 Apache Fluent API:

Request.Post(mainProperties.getPartnerURL())
                .addHeader("Signature", SecurityHelper.getSignature(requestBody.getBytes("UTF-8"),
                        mainProperties.getPartnerKey()))
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .connectTimeout(mainProperties.getRequestTimeoutMillis())
                .bodyByteArray(requestBody.getBytes(UTF_8))
                .execute().returnContent().asString();

但是我已經將 so_keepalive 參數設置為套接字。 可以使用 HttpClient 來完成:

    SocketConfig socketConfig = SocketConfig.custom()
            .setSoKeepAlive(true)
            .build();

    RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(mainProperties.getRequestTimeoutMillis())
            .build();

    CloseableHttpClient httpClient = HttpClientBuilder.create()
            .setDefaultSocketConfig(socketConfig)
            .setDefaultRequestConfig(requestConfig)
            .build();
            
    HttpPost post = new HttpPost(mainProperties.getPartnerURL());

    post.addHeader("Signature", SecurityHelper.getSignature(requestBody.getBytes("UTF-8"),
                mainProperties.getPartnerKey()));
    post.addHeader("Content-Type", "text/xml");
    post.setEntity(new StringEntity(requestBody, UTF_8));

    CloseableHttpResponse response = httpClient.execute(post);
    return EntityUtils.toString(response.getEntity(), UTF_8);

然后在我的sysctl.conf中設置的net.ipv4.tcp_keepalive_time=350 (應用更改需要 sysctl -p)應用於新連接,可以這樣檢查:

netstat -o | grep <remote-host>
tcp6       0      0 ip-172-30-4-233.e:50414 <remote-host>:http ESTABLISHED **keepalive (152.12/0/0)**

因此,從最后一個數據包 350 秒后發送的 TCP-Keep-Alive 數據包沒有響應會關閉 ESTABLISHED 連接。 通過 tcp 轉儲可以看到所有 TCP-Keep-Alive 數據包:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM