来自HttpClient的重复请求

我在Android上使用HttpClient 4.0.1 …我做了一个POST请求与一个标头设置是目前毫秒…我看到请求两次在对方的几个毫秒(5-10)的服务器。但是我设置的头文件对于这两个请求都是一样的。 这种情况非常偶然…我看到wireshark之​​间的请求没有真正的区别…我只是不知道如何发生这种情况。 任何人遇到此之前,或有任何提示如何进一步debugging呢?

这里是我用来创build客户端的代码:

public static HttpClient getAndroidHttpClient(final int timeOut) { // set up the schemas SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443)); // set up our params HttpParams params = new BasicHttpParams(); params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOut); params.setIntParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, timeOut); params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeOut); params.setLongParameter(ConnManagerPNames.TIMEOUT, timeOut); params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1); params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1)); params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false); HttpProtocolParams.setUserAgent(params, "android-client-v1.0"); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, "utf8"); ThreadSafeClientConnManager conman = new ThreadSafeClientConnManager(params, schemeRegistry); DefaultHttpClient defaultHttpClient = new DefaultHttpClient(conman, params); return defaultHttpClient; } 

Solutions Collecting From Web of "来自HttpClient的重复请求"

所以看起来发生在这里的是你的客户端发送一个请求,没有得到及时的回应,并因此再次重试相同的请求(因为它应该)。 这反过来又会导致多个POST请求被发送到您的服务器(几乎是连续的),您的服务器目前无法正确处理。

要validation/debugging,请尝试禁用HTTP重试,如下所示:

 defaultHttpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler (0, false)); 

这当然会处理您的重复请求问题,但是会引入另一个更严重的问题; 即它会尝试一次 (也只会一次)而失败。 从我的评论中获得的信息,可以尝试以下几点:

由于我没有关于客户端架构的详细信息,请使用伪代码

处理多个POSTS

  • 禁用自动重试(如上)
  • 将你的POST请求封装在一个类似于这个实现的循环中
  • 然后,在您的手动重试之间sleep ,或者实施您的指数退避版本

无论如何,你的服务器需要能够以合理的方式处理重复的请求,这是HTTP的后果。 但是,至less给它一个机会来处理第一个被轰炸之前的重复。

我build议处理请求时所需的第一步是设置某种forms的(重复) 标志 。 然后,如果/当它收到一个重复,它继续处理第一个请求(像往常一样),并默默地忽略了这些重复。

简而言之,这个整个计划的重点就是给你的服务器一个机会来设置伪装标志 。 之后,根据需要丢弃(或处理)重复请求是您服务器的工作。 这一切都有道理吗?

我不能说与Android附带的HttpClient版本,因为它现在是基于一个非常旧的前testing版快照分叉。 但是,如果您使用的是Apache HttpClient 4.x的股票版本,则不会自动重试POST或PUT请求,除非进行了其他configuration。

在您的特定情况下,我怀疑由于连接丢失或类似的networking问题,HTTP消息被无线驱动程序重新传输。 HTTP不是有保证的传送协议。 HTTP消息可以由低层传输重新发送。 您的应用程序必须准备好处理重复的HTTP消息。

重试策略我们可以定制

与排球请求

stringRequest.setRetryPolicy(new DefaultRetryPolicy(0,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); volleySingleton.addToRequestQueue(stringRequest);