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.dll
和libeay32.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越大,解码越多
所有这些开销加起来。
您可以采取一些措施来减少 一些 开销:
预先预加载 OpenSSL(Indy 有一个 LoadOpenSSLLibrary()
函数)。
通过使用相同的 TIdHTTP
/TIdSSLIOHandlerSocketOpenSSL
对象,并通过设置TIdHTTP.Request.Connection
属性 到 keep-alive
and/or 将 TIdHTTP.ProtocolVersion
属性 设置为 pv1_1
(keep-alive 是 HTTP 1.1 中的默认行为, 但不是 1.0).
根据您要对下载的 HTML 执行的操作,您可以考虑将其下载到 TStream
而不是 String
。这样,TIdHTTP.Get()
将跳过缓存和字符集解码步骤,下载的任何内容都将按原样直接保存到您提供的 TStream
。如果你实际上根本不需要 HTML,你可以传递一个 nil
TStream
来告诉 Get()
根本不要 cache/process 下载的数据。
此外,请检查向 YouTube 发送请求是否实际上只生成一个 request/response,而不是服务器使用 HTTP 重定向导致发送额外的请求,从而花费更多时间到达最终内容(查看 TIdHTTP.OnRedirect
事件是否被触发)。请求 Pixar 的主页不太可能做到这一点。
将一个 TIdHTTP
组件和一个 TIdSSLIOHandlerSocketOpenSSL
组件放在 VCL 窗体上。
不要为 IdHTTP1.IOHandler
属性.
然后从HTTPURL获取HTML,例如:
sHTML := IdHTTP1.Get('http://www.pixar.com');
• 这非常快并且效果很好。
然后将IdSSLIOHandlerSocketOpenSSL1
分配给IdHTTP1.IOHandler
属性.
然后把ssleay32.dll
和libeay32.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越大,解码越多
所有这些开销加起来。
您可以采取一些措施来减少 一些 开销:
预先预加载 OpenSSL(Indy 有一个
LoadOpenSSLLibrary()
函数)。通过使用相同的
TIdHTTP
/TIdSSLIOHandlerSocketOpenSSL
对象,并通过设置TIdHTTP.Request.Connection
属性 到keep-alive
and/or 将TIdHTTP.ProtocolVersion
属性 设置为pv1_1
(keep-alive 是 HTTP 1.1 中的默认行为, 但不是 1.0).根据您要对下载的 HTML 执行的操作,您可以考虑将其下载到
TStream
而不是String
。这样,TIdHTTP.Get()
将跳过缓存和字符集解码步骤,下载的任何内容都将按原样直接保存到您提供的TStream
。如果你实际上根本不需要 HTML,你可以传递一个nil
TStream
来告诉Get()
根本不要 cache/process 下载的数据。
此外,请检查向 YouTube 发送请求是否实际上只生成一个 request/response,而不是服务器使用 HTTP 重定向导致发送额外的请求,从而花费更多时间到达最终内容(查看 TIdHTTP.OnRedirect
事件是否被触发)。请求 Pixar 的主页不太可能做到这一点。