如何在测试公共代理时可靠地重现curl_multi超时

时间:2019-02-22 12:40:20

标签: php c curl bug-tracking curl-multi

相关信息:issue 3602 on GitHub

我正在从事一个收集和测试公共/免费代理的项目,并注意到当我使用curl_multi接口测试这些代理时,有时会遇到许多28(timeout)错误。如果我仅测试每个代理,就永远不会发生这种情况。

问题在于此问题的再现性不可靠,并且不会总是出现,可能是卷曲的东西或其他东西

不幸的是,我不是一个如此深入的网络调试器,我也不知道如何在更深层次上调试此问题,但是我编写了2个C测试程序(其中一个最初是written by Daniel Stenberg,但我修改了一下)。这两个C程序使用curl测试了407个公共代理

  1. 具有curl_multi接口(有问题)

  2. 在许多线程上都有卷曲,每个卷曲都在一个线程上运行。 (没有问题)

These are the 2 C programs I wrote for testing我不是C开发人员,所以请让我知道您在2个程序中发现的任何错误。

这是一个月前我用来重现此问题的original PHP class

还有these are the 2 C programs tests results。您会注意到,使用curl_multi超时进行的测试,而由curl-threads进行的超时是稳定的(407个代理中的大约50个正在工作)。

这是测试结果的样本。 请注意第4列和第5列,以了解卷发线程如何超时约170次并成功连接约40次。其中,curl_multi在407个代理中建立了0个成功的连接,并且超时约300次。

column(1) : #
column(2) : time(UTC)
column(3) : total execution time (seconds)
column(4) : no error 0 (how many requests result in no error CURLE_OK)
column(5) : error 28 (how many requests result in error 28 CURLE_OPERATION_TIMEDOUT)
column(6) : error 7 (how many requests result in error 7 CURLE_COULDNT_CONNECT)
column(7) : error 35 (how many requests result in error 35 CURLE_SSL_CONNECT_ERROR)
column(8) : error 56 (how many requests result in error 56 CURLE_RECV_ERROR)
column(9) : other errors (how many requests result in errors other than the above)
column(10) : program that used the curl
column(11) : cURL version

c(1)    c(2)           c(3)c(4)c(5)c(6)c(7)c(8)c(9) c(10)                  c(11)
267 2019-3-28 01:58:01  40  43  176 183 1   4   0   C (curl - threads) (Linux Fedora)   7.59.0
268 2019-3-28 01:59:01  30  0   286 110 1   10  0   C (curl-multi one thread) (Linux Fedora)    7.59.0
269 2019-3-28 02:00:01  30  46  169 181 1   8   2   C (curl - threads) (Linux Fedora)   7.59.0
270 2019-3-28 02:01:01  31  0   331 74  1   1   0   C (curl-multi one thread) (Linux Fedora)    7.59.0
271 2019-3-28 02:02:01  30  42  173 186 1   4   1   C (curl - threads) (Linux Fedora)   7.59.0
272 2019-3-28 02:03:01  30  0   277 116 1   13  0   C (curl-multi one thread) (Linux Fedora)    7.59.0

为什么curl_multi超时与大多数连接不一致,而curl线程却从来没有这样做?

我下载了Wireshark,并在运行2个C程序时用它捕获流量,我也filtered将该流量files到2 C程序使用的代理列表,并保存了{{3} }。

curl-threads程序(预期行为)

在407个代理中有63个成功的连接和158个连接超时。

curl_multi程序( un 预期的行为)

在407个代理中,

0个成功连接和272个连接超时。

您可以使用Wireshark打开.pcapng文件,并在我的计算机上看到记录的流量,同时出现两种预期/意外的行为。我过滤了到407个代理IP的流量,并在30秒的卷曲限制后将Wireshark保持打开状态一会儿,因为我注意到某些数据包仍在显示。我不知道Wireshark和这种级别的网络,但是我认为这可能很有用。


有关带宽的说明:

在wireshark中打开curl_threads程序的.pcapng文件(正常行为),然后转到“统计信息”>“对话”。您会看到这样的窗口

enter image description here

我已经复制了数据并将它们here保存在GitHuB上,现在计算从A-> B和B-> A发送的字节的Sum

  

正常工作所需的整个带宽约为692.8 KB。

2 个答案:

答案 0 :(得分:1)

对我来说,您似乎对curl本身没有问题,但是如果拒绝连接,则可以同时与代理服务器建立太多连接。您可能会被永久列入黑名单或一段时间。

通过从当前IP运行curl并检查状态,以检查是否建立了多少连接,拒绝了多少连接,超时了多少。重复几次并收集平均值。然后将服务器更改为其他具有不同IP的服务器,并检查那里的统计信息。第一次运行时,您应该有更好的统计信息,如果您在新IP上重复测试,可能只会变得更糟。 好的主意可能是不使用代理的所有池来进行统计,而是从它们中选择一个片段并检查实际IP并在新IP上重复该检查,因此,如果原因是您滥用服务,则不要将自己列入黑名单所有代理,但如果确实如此,仍需要下一组“未修改”的代理在新IP上对其进行测试。 请注意,即使代理的IP位于不同的位置,它们也可以属于同一服务提供商。该代理的所有代理服务可能都有一个滥用列表,因此,如果您对在一个国家/地区进行的请求数量不满意,甚至在连接到另一个国家/地区代理之前,您也可能会在另一个国家/地区遭到屏蔽。 / p>

如果您仍然想检查它是否不卷曲,则可以设置一个多份的测试环境。您可以将这个测试环境传递给curl维护人员,以便他可以复制错误。 您可以使用docker创建10、20或100个代理服务器并连接到它们,以查看curl是否有问题。

您将需要 docker它可以安装在Win / Mac / Linux
proxy image之一以创建代理
为容器创建网络tutorial(桥接应该可以)
将容器连接到网络--network
可以为每个代理容器设置其--ip
通过使用--volume
的mountig错误日志/配置文件/子目录,使每个代理容器都可以读取配置和写入错误日志(因此您可以阅读为什么它们断开连接的原因) 并且所有代理容器都应为runnig

您可以通过两种方式连接到在容器内运行的代理。 如果您希望在这些容器外部卷曲,则需要使用-p将这些代理的端口从容器暴露到外界(在您的情况下为curl)。

您可以使用另一个具有linux + curl的容器映像。例如,Alpine linux + curl并以与代理相同的方式将其连接到同一网络。如果这样做,则无需发布(公开)代理服务器的端口,也不必考虑应该为该特定代理服务器公开多少个代理服务器端口。

在每个步骤中您都可以发出命令

docker ps -a

查看所有容器及其状态。

停止并删除所有容器(不是来自它们的图像,而是正在运行的容器),以防容器中有些错误而退出。

docker stop $(docker ps -aq) && docker rm $(docker ps -aq)

或停止并从列表中删除特定容器

docker stop <container-id>
docker rm <container-id>

查看连接到网桥网络的所有容器(默认)

docker network inspect bridge

如果您确认与本地计算机上的代理服务器连接确实存在问题,则可以使curl的维护者进行复制。

只需将上述所有命令创建所有代理,即可将它们连接到网络等文件,例如以{p>开头的replicate.sh脚本

#!/bin/sh

and your comands here

保存该文件,然后发出命令

chmod +x ./replicate.sh

使其可执行。

您可以运行它来仔细检查一切是否按预期进行

./replicate.sh

并将curl的维护者发送到您遇到问题的环境。

如果您不想放置诸如doker run之类的许多命令来运行代理,则可以使用docker compose来代替,它可以在一个文件中定义整个测试环境。

如果您运行大量容器,则可以限制资源,例如memory每个容器消耗的资源,可能在代理太多的情况下为您提供帮助

答案 1 :(得分:1)

尝试在一个线程中具有400个开放连接。甚至处理,就此而言。您可能会超负荷使用代理,因此它们可能会将您列入黑名单(拒绝服务安全)。否则您的出站网络可能会限制打开的连接数。