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

如何从HttpClient设置TCP保持活动?

隗俊誉
2023-03-14

驻留在AWS专用子网中的Java应用程序通过AWS Nat网关连接到http服务器。我正在通过HttpClient向HTTP服务器调用POST请求。完成该请求需要10分钟以上。我已将套接字超时和连接超时配置为1小时,因为这是一项后台任务。但是中间AWS NAT网关将在300秒[5分钟]后发回RST数据包,并导致连接重置,我无法增加NAT网关超时。所以我需要从我的应用程序方面处理这个问题。

我的策略是使用TCP保持活动时间,即每隔240秒发送一个数据包,以保持连接处于活动状态。我已将其配置如下

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

但是在执行程序时,保持活着没有启用,连接也会像以前一样失败。

我已经用netstat-o选项对此进行了检查,如下所示,keep-alive处于关闭状态

tcp        0      0 192.168.1.141:43770     public_ip:80          ESTABLISHED 18134/java           off (0.00/0/0)

是否有任何方法可以使用httpclient从java代码设置TCP保持活动状态。我还可以看到HttpConnectionParams已被弃用。但我找不到任何新的类,可以设置保持活力

共有3个答案

伍心水
2023-03-14

上面使用Socket的方法在tcp_keepalive_intvl值重置低于AWS网络负载平衡器超时的情况下运行良好。使用这两种方法,重置允许java小时连接的NLB tcp空闲超时。

欧渝
2023-03-14

保持HTTP连接打开但长时间处于非活动状态是一个糟糕的设计选择。HTTP是一种请求-响应协议,意味着请求和响应是快速的。

打开连接会保存资源。从服务器(以及网络防火墙和路由器)的角度来看,打开连接并开始请求(在您的情况下是POST)但长时间不发送任何字节的客户端与永远不会发送任何数据的客户端没有区别,因为它是错误的或恶意的(进行DOS攻击)。服务器(和网络硬件)正确地得出结论,正确的做法是关闭连接并回收用于连接的资源。你正试图与有充分理由的正确行为作斗争。即使您设法解决了TCP关闭问题,您也会发现其他问题,如HTTP服务器超时和数据库超时。

您应该重新考虑这两个组件之间的通信设计。也就是说,这看起来像一个XY问题。你可以考虑

  • 让客户端在启动POST之前等待,直到它有一个完整的上载要执行。
  • 将上传内容分割成更小、更频繁的上传内容。
  • 使用HTTP以外的协议
梁丘招
2023-03-14

我找到了解决问题的办法。奇怪的情况是有没有办法,我可以使用一些建设者类在http客户端传递套接字保持活着。我在问题中指定的一个方法是使用HttpConnectionParams,如下所示,但是这不起作用,这个类现在不建议使用。

HttpParams params = httpClient.getParams();
HttpConnectionParams.setSoKeepalive(params, true);

所以在检查ApacheHTTP文档时,我可以看到现在连接参数通过RequestConfig类传递给httpclient。此类生成器提供了设置连接超时和套接字超时的解决方案。但是检查一下这个的socource代码,我看不到启用SocketKeepAlive的选项,这正是我们想要的。因此,唯一的解决方案是使用SocketBuilder类直接创建套接字,并将其传递给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值,在套接字中正确地设置了保活

tcp        0      0 localip:48314     public_ip:443     ESTABLISHED 14863/java          keepalive (234.11/0/0)

如果有人有更好的解决方案,可以从Requestconfig类或任何其他高级构建器类中启用Socket保持活动,我愿意听取建议。

 类似资料:
  • 问题内容: 我正在使用POST方法。我需要创建一次,并且应该使用Keep Alive Connection。但是我认为,它每次都会建立一个新的连接。 因此,我需要使用 保持活动 连接。 这是我的代码段,很多帮助将不胜感激。 而且logcat日志是: 问题答案: 10:07:29.746:D / org.apache.http.headers(1529):>>连接:保持活动 您正在要求保持活动状态。

  • 我正在创建一个客户端服务器应用程序。服务器已经设计好,等待从客户端连接。现在在客户机部分中,我希望在应用程序的整个生命周期中保持连接活动,并且只有当主客户机应用程序关闭或关闭或者服务器关闭它时,连接才会关闭。 在处理程序中我有:

  • 我正在我的Linux box上试验TCP keep alive,并编写了以下小型服务器: 然后我将系统范围的TCP保持活动状态设置调整为: 然后我从Windows连接到服务器,并运行Wireshark跟踪以查看保持活动的数据包。下图显示了结果。

  • 在nGinx服务器端,客户端的连接保持活动时间设置为30秒。但是使用这段代码和附加的日志,HttpClient 4.3。不尊重keep alive并在每次请求后关闭连接。为什么会这样? 我反复尝试netstat-an,发现客户机在for循环执行期间的不同时间打开了不同的端口,每2秒就有一次FIN状态,然后得出了这个结论。 下面给出的日志还显示,everyrequest之后连接已关闭 这些是日志。

  • 对于一些我们无法解决的问题,我想在Apache HttpClient 3.1上禁用keep alive。然而,我在互联网上找不到这方面的任何资源。你知道怎么做吗?

  • 在带有PoolingHttpClientConnectionManager的Apache HttpClient中,Keep-Alive策略是否会更改活动连接在从连接池中删除之前保持活动状态的时间量?还是只会关闭空闲连接? 例如,如果我将Keep Alive策略设置为每个请求返回5秒,并且我使用相同的连接每2秒点击一次URL/路由,那么Keep Alive策略是否会导致该连接离开池?或者它会留在池中