我位于 AWS 私有(private)子网中的 Java 应用程序通过 AWS Nat 网关连接到 http 服务器。我正在通过 HttpClient
调用 POST 请求到 HTTP 服务器。该请求将需要 10 多分钟才能完成。我已经配置了 1 小时的套接字超时和连接超时,因为这是一个后台任务。但是中间 AWS NAT 网关将在 300 秒 [5 分钟] 后发回 RST 数据包并导致连接重置,我无法增加 NAT 网关超时。所以我需要从我的应用程序端处理这个问题。
我的策略是使用 TCP 保持 Activity 时间,它将每 240 秒发送一个数据包以保持连接处于 Activity 状态。我已经配置了这个
如下
CloseableHttpClient httpClient = HttpClients.createDefault()
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 3600000); //connection Timeout
HttpConnectionParams.setSoTimeout(params, 3600000); // Socket Time out
HttpConnectionParams.setSoKeepalive(params, true); //Enable Socket level keep alive time
然后通过execute方法调用post请求HttpPost post = new HttpPost("http://url");
HttpResponse response = httpClient.execute(post);
由于我使用的是 Linux 系统,因此我使用以下 sysctl 值配置了服务器:sysctl -w net.ipv4.tcp_keepalive_time=240
sysctl -w net.ipv4.tcp_keepalive_intvl=240
sysctl -w net.ipv4.tcp_keepalive_probes=10
但是在执行程序时,没有启用保持 Activity ,并且连接像以前一样失败。我已经用 netstat -o 选项检查了这个,如下所示保持 Activity 关闭
tcp 0 0 192.168.1.141:43770 public_ip:80 ESTABLISHED 18134/java off (0.00/0/0)
有什么方法可以使用 httpclient 从 java 代码中设置 TCP 保持 Activity 状态。我也可以看到HttpConnectionParams
已弃用。但我找不到任何可以设置保持活力的新类(class)
最佳答案
我找到了解决问题的方法。奇怪的情况是我无法在 httpclient 中使用一些构建器类来传递套接字保持 Activity 。我在问题中指定的一种方法是使用 HttpConnectionParams 如下,但这不起作用,现在不推荐使用此类。
HttpParams params = httpClient.getParams();
HttpConnectionParams.setSoKeepalive(params, true);
因此,在检查 apache http 文档时,我可以看到现在连接参数通过 RequestConfig 类传递给 httpclient。此类的构建器提供了设置 connection_time_out 和 socket_time_out 的解决方案。但是检查这个源代码我看不到启用 SocketKeepAlive 的选项,这正是我们想要的。所以唯一的解决方案是直接使用 SocketBuilder 类创建一个 Socket 并将其传递给 HttpClientBuilder。
以下是工作代码
SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).setSoTimeout(3600000).build(); //We need to set socket keep alive
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(3600000).build();
CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).
setDefaultSocketConfig(socketConfig).build();
HttpPost post = new HttpPost(url.toString());
HttpResponse response = httpClient.execute(post);
在上面执行时,我可以看到根据我在 linux 内核中设置的 sysctl 值在套接字中正确设置了保持 Activity 状态
tcp 0 0 localip:48314 public_ip:443 ESTABLISHED 14863/java keepalive (234.11/0/0)
如果有人有更好的解决方案来从 Requestconfig 类或任何其他高级构建器类中启用 Socket Keep alive,我愿意接受建议。
关于java - 如何从 HttpClient 设置 TCP 保持 Activity 状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53375222/