通过 Curl API 下载 Curl 非常慢
Curl download through Curl API is very slow
我正在使用 CURL 库下载文件。我们使用 https:// 和 TLS 1.2 。
使用的卷曲版本是 7.48.0。我们正在观察一个奇怪的问题。对于大小为 224 MB 的文件,Curl 下载在服务器和客户端之间运行非常缓慢。如果我们使用 curl 的命令行工具它非常快,但如果我们从应用程序端调用 "curl_easy_perform" 则情况并非如此。
此外,我们使用 --libcurl 选项来检查命令行和我们的代码之间的区别,并且有 none。我们使用与命令行工具相同的选项,但通过直接调用 curl_easy_perform 下载仍然很慢。
如果我们从其他服务器和同一个客户端下载它工作正常。但是,只有在特定服务器上,我们才会遇到下载时间问题。
进一步调试,我们发现 netstat 输出显示 tcp 套接字的接收队列非常高。但是,不清楚为什么这只会通过我们的程序而不是命令行出现问题,即使设置了相同的选项也是如此。
原来这个问题是因为写回调,这在这个服务器上花费了时间。在应用层的write回调中,我们已经完成了malloc、memcpy和free复制接收到的新数据。除一台服务器外,所有服务器都可以正常工作。与此服务器连接的不同之处在于,Curl 在 Write 回调中给出 16378 后跟 6 字节的数据,而对于它工作正常的其他服务器,它总是给出 16384 字节的数据。这与设备上默认为套接字缓冲区设置的 rmem_max 大小相同。不知道为什么对于特定的服务器(Wildfly),它分成 16378 个字节,然后是 6 个字节。这导致 224 MB 文件大小下载的连续 malloc、memcpy 和空闲周期。结果,从套接字读取变得非常慢,导致下载缓慢。在 Curl 命令行工具中,write 回调的编写方式不同,其中打开一个文件,并通过在接收到数据时定期调用 fwrite 将数据写入该文件,然后在接收到所有数据后调用 fclose。与 malloc、memcpy 和 free 操作相比,这是非常快的操作。所以 curl 命令行工具可以很好地下载相同的文件。我们改变了我们的写回调以与 curl 命令行的方式保持一致,它解决了这个问题。
但是,对于这个特定的服务器,Curl 将数据分成 16378 + 6 字节的原因尚不清楚,我将进一步调查。
我正在使用 CURL 库下载文件。我们使用 https:// 和 TLS 1.2 。 使用的卷曲版本是 7.48.0。我们正在观察一个奇怪的问题。对于大小为 224 MB 的文件,Curl 下载在服务器和客户端之间运行非常缓慢。如果我们使用 curl 的命令行工具它非常快,但如果我们从应用程序端调用 "curl_easy_perform" 则情况并非如此。
此外,我们使用 --libcurl 选项来检查命令行和我们的代码之间的区别,并且有 none。我们使用与命令行工具相同的选项,但通过直接调用 curl_easy_perform 下载仍然很慢。
如果我们从其他服务器和同一个客户端下载它工作正常。但是,只有在特定服务器上,我们才会遇到下载时间问题。 进一步调试,我们发现 netstat 输出显示 tcp 套接字的接收队列非常高。但是,不清楚为什么这只会通过我们的程序而不是命令行出现问题,即使设置了相同的选项也是如此。
原来这个问题是因为写回调,这在这个服务器上花费了时间。在应用层的write回调中,我们已经完成了malloc、memcpy和free复制接收到的新数据。除一台服务器外,所有服务器都可以正常工作。与此服务器连接的不同之处在于,Curl 在 Write 回调中给出 16378 后跟 6 字节的数据,而对于它工作正常的其他服务器,它总是给出 16384 字节的数据。这与设备上默认为套接字缓冲区设置的 rmem_max 大小相同。不知道为什么对于特定的服务器(Wildfly),它分成 16378 个字节,然后是 6 个字节。这导致 224 MB 文件大小下载的连续 malloc、memcpy 和空闲周期。结果,从套接字读取变得非常慢,导致下载缓慢。在 Curl 命令行工具中,write 回调的编写方式不同,其中打开一个文件,并通过在接收到数据时定期调用 fwrite 将数据写入该文件,然后在接收到所有数据后调用 fclose。与 malloc、memcpy 和 free 操作相比,这是非常快的操作。所以 curl 命令行工具可以很好地下载相同的文件。我们改变了我们的写回调以与 curl 命令行的方式保持一致,它解决了这个问题。 但是,对于这个特定的服务器,Curl 将数据分成 16378 + 6 字节的原因尚不清楚,我将进一步调查。