TIdHTTP.Get 使用 HTTPS URL 非常慢

TIdHTTP.Get very slow with HTTPS URLs

将一个 TIdHTTP 组件和一个 TIdSSLIOHandlerSocketOpenSSL 组件放在 VCL 窗体上。

不要为 IdHTTP1.IOHandler 属性.

分配任何内容

然后从HTTPURL获取HTML,例如:

sHTML := IdHTTP1.Get('http://www.pixar.com');

• 这非常快并且效果很好。

然后将IdSSLIOHandlerSocketOpenSSL1分配给IdHTTP1.IOHandler 属性.

然后把ssleay32.dlllibeay32.dll放到应用目录下

然后从HTTPSURL获取HTML,例如:

sHTML := IdHTTP1.Get('https://www.youtube.com/watch?v=CB1Pukr0nFQ');

• 这非常慢,几乎需要 4 (!) 秒才能获得 HTML。

那么,为什么使用 HTTPS URL 这么慢,而从 HTTP 和 HTTPS URLs 获取 HTML 的最快方法是什么?

加密和解密 HTML 内容比传输未加密内容的开销更大。

在请求和传输内容之前与服务器建立安全会话也会产生开销(请求和响应均已加密)。

此外,在发出 HTTPS 请求时,如果尚未加载 OpenSSL,则加载和初始化 OpenSSL 库会产生开销。

此外,您调用的 TIdHTTP.Get() 版本 returns 是 String,因此所有下载的数据都必须缓冲在内存中,然后字符集解码为 UTF -16。 HTML越大,解码越多

所有这些开销加起来。

您可以采取一些措施来减少 一些 开销:

  1. 预先预加载 OpenSSL(Indy 有一个 LoadOpenSSLLibrary() 函数)。

  2. 通过使用相同的 TIdHTTP/TIdSSLIOHandlerSocketOpenSSL 对象,并通过设置TIdHTTP.Request.Connection 属性 到 keep-alive and/or 将 TIdHTTP.ProtocolVersion 属性 设置为 pv1_1 (keep-alive 是 HTTP 1.1 中的默认行为, 但不是 1.0).

  3. 根据您要对下载的 HTML 执行的操作,您可以考虑将其下载到 TStream 而不是 String。这样,TIdHTTP.Get() 将跳过缓存和字符集解码步骤,下载的任何内容都将按原样直接保存到您提供的 TStream。如果你实际上根本不需要 HTML,你可以传递一个 nil TStream 来告诉 Get() 根本不要 cache/process 下载的数据。

此外,请检查向 YouTube 发送请求是否实际上只生成一个 request/response,而不是服务器使用 HTTP 重定向导致发送额外的请求,从而花费更多时间到达最终内容(查看 TIdHTTP.OnRedirect 事件是否被触发)。请求 Pixar 的主页不太可能做到这一点。