Android:第一个http响应总是需要更长时间(即使没有保持活动)

时间:2014-03-19 22:08:37

标签: android json httpurlconnection keep-alive httpconnection

我使用类HttpUrlConnection来请求JSON响应

我意识到无论我是否设置

System.setProperty("http.keepAlive", "false");

第一个响应总是需要更长时间,而下一个响应非常快,有和没有keepAlive。我甚至没有使用SSL。

请注意,我的应用程序不需要对服务器执行任何身份验证,因此没有任何对Web服务的启动调用。我对Web服务的第一个请求实际上是第一个。

我也在使用" netstat"验证服务器端,通过在Android客户端上设置 keepAlive false ,连接立即消失,而不指定 keepAlive false 他们一直待在" ESTABLISHED"。

即使连接没有持续存在,您如何解释后续响应更快?

ANDROID CODE

line 1) URL url = new URL(stringUrl);
line 2) HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
line 3) InputStream instream = new BufferedInputStream(urlConnection.getInputStream());

直到第2行,所有事情都会很快被执行,无论是否使用keepAlive。第一个请求中的第3行大约需要3秒,而在随后的所有请求中总是小于1秒。每个请求都是大约0.5KB gzip压缩。

系统

  • 我正在使用通过3G连接的Nexus 5进行测试
  • 我的网络服务是用Go编写的,在CentOS 6.4 Linux服务器上运行
  • 我使用的是标准的tcp v4

更新

目前我决定使用一个技巧:当片段恢复时,我向服务器发出HTTP HEAD请求。通过这种方式,接下来10秒内的所有后续呼叫都非常快。如果用户等待超过10秒,那么第一个将慢,而下一个将再次快速。这一切都在不使用KeepAlive的情况下发生。

现在这是一个非常大的谜团。它看起来像某种清醒"持续约10秒的时间。我不认为我的代码有什么奇怪的东西会导致这种情况。还因为一切似乎都发生在我上面报道的第3行。

已解决!感谢Mark Allison!

这是一个非常明确的解释: http://developer.android.com/training/efficient-downloads/efficient-network-access.html

此外,使用Android DDMS的网络统计信息可以轻松监控所有内容。如果您从上次请求中等待几秒钟(让我们说20),您可以看到传输新请求需要2秒钟。

3 个答案:

答案 0 :(得分:2)

我怀疑您所看到的延迟只是由蜂窝无线电从低功率或空闲状态转换为全功率(可能需要超过2秒)。

Efficient Data Transfer上查看Reto Meier优秀的DevBytes系列,深入解释发生了什么。

答案 1 :(得分:0)

  1. 第一个请求显然无法利用keep-alive,因为谢天谢地,Android并没有将连接保持活动数分钟或数小时。只有后续请求才能重复使用保持活动连接,并且只能在很短的时间后重复使用。

  2. 很自然,你必须排队等候。在conn.getResponseCode()conn.getInputStream()之前,HttpURLConnection处于CREATED状态。在进入CONNECTED状态之前,没有网络活动。 Buffered*在这里不应该有任何区别。

  3. 我在使用SSL时发现长时间延迟,服务器和设备之间存在时间偏移。当使用非冷启动的仿真器时,这种情况经常发生。为此,我在测试之前运行了一个小脚本。 PC和仿真器处于同一时区是非常重要的,否则它会非常反应:(见下文,因为内联命令很难显示)。

  4. 我可以想象,当没有活动时,Android可以节省电池,使3G进入睡眠模式。这只是猜测,但您可以通过与其他应用程序(浏览器,推特,...)创建一些其他网络活动进行测试,然后查看您的应用程序是否需要相同的长时间"思考时间"直到第一次连接。

  5. 还有其他很好的选择可以浪费时间:DNS解析,服务器端"睡眠" (例如虚拟机加载"内存"来自磁盘)。

  6. 设置Android模拟器时间的命令:

    adb -e shell date -s `date +"%Y%m%d.%H%M%S"`
    

    修改

    要进一步分析问题,您可以在服务器上运行tcpdumpHere is tutorial万一你不清楚。将转储存储到文件(pcap),然后您可以使用wireshark查看它们。根据CentOS服务器上的流量,您必须设置一些过滤器,以便只记录Android设备的流量。我希望这能为这个问题提供一些见解。

    要将您的服务器排除在坏人之外,您可以使用curl命令创建一个与您的应用程序等效的小脚本。

    您可以在没有数据库或其他i / o依赖项的情况下创建超小型服务并测量性能。我不知道" Go",但最好的是Apache或nginx提供的静态JSON文件。如果您只有Go,那么请选择/ping -> { echo "pong" }之类的内容。请告诉我们您的测量和观察结果。

答案 2 :(得分:-1)

我建议您使用此库

,而不是使用这么多类

你可以看看这里

http://loopj.com/android-async-http/

你的代码会变得非常少,而不是声明编写大量代码的类,你可以只使用4行代码

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
@Override
public void onSuccess(String response) {
System.out.println(response);
   }
});

非常快速地确定响应非常有效(1或2秒,包括解析)。

我希望这会帮助你。 :)