我在Android上使用HttpClient 4.0.1 ...我发出了一个POST请求,其头标设置为当前的毫米...我看到该请求在几毫秒(5-10)的范围内两次命中服务器彼此..但我设置的标题对于两个请求都是相同的。这种情况非常偶然发生......我看到wireshark中的请求之间没有真正的区别......我不知道这是怎么发生的。有人之前遇到过这个或者有关于如何进一步调试它的任何提示吗?
这是我用来创建客户端的代码:
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;
}
答案 0 :(得分:19)
所以这里似乎发生的是你的客户端发送请求,没有及时得到响应,结果再次重试相同的请求(应该如此)。反过来,这会导致多个POST
请求被发送到您的服务器(几乎连续),您的服务器当前无法正确处理这些请求。
要验证/调试此问题,请尝试按如下方式禁用HTTP重试:
defaultHttpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler
(0, false));
这当然会处理您的重复请求问题,但随后会引入另一个更严重的问题;也就是说,它会尝试一次(只有一次)并失败。根据您从评论中获得的信息,您可以尝试以下几个想法:
请使用伪代码,因为我没有关于客户端架构的所有细节
连续处理多个帖子
POST
个请求换成类似于this实施方式的循环sleep
或实施您的exponential backoff 无论如何,您的服务器将需要以合理的方式处理重复请求的功能,这是HTTP的后续。但是,你至少有机会在重复轰炸之前处理第一个。
我建议处理请求时的第一个步骤是设置某种形式的(重复)标志。然后,如果/当它收到一个欺骗,它继续处理第一个请求(像往常一样)并默默地忽略欺骗。
总而言之,整个计划的重点是让您的服务器有机会设置欺骗标志。之后,根据需要丢弃(或处理)重复请求是您服务器的工作。这一切都有意义吗?
答案 1 :(得分:1)
我不能代表Android附带的HttpClient版本,因为它现在基于一个非常古老的BETA前快照实际上是一个分支。但是,如果您使用的是Apache HttpClient 4.x的库存版本,则不会会自动重试POST或PUT请求,除非另有配置。
在您的特定情况下,我怀疑由于连接丢失或类似的网络问题,无线驱动程序会重新传输HTTP消息。 HTTP不是保证传递协议。 HTTP消息可以由较低级别的传输重新发送。您的应用程序必须准备好处理重复的HTTP消息。
答案 2 :(得分:0)
重试政策我们可以自定义
WITH VOLLEY REQUEST
stringRequest.setRetryPolicy(new DefaultRetryPolicy( 0, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); volleySingleton.addToRequestQueue(stringRequest);