代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

tcp、http与多线程技术

  •  6
  • Robert S. Barnes Antoni  · 技术社区  · 14 年前

    我试图了解我得到的性能数据以及如何确定最佳线程数。

    我的结果见这篇文章的底部

    我用Perl编写了一个实验性的多线程Web客户机,它下载一个页面,获取每个图像标记的源代码并下载图像—丢弃数据。

    它使用非阻塞连接,每个文件的初始超时为10秒,每次超时后加倍,然后重试。它还缓存IP地址,因此每个线程只需进行一次DNS查找。

    通过2.5Mbit连接,从1316个文件中下载的数据总量为2271122字节 http://hubblesite.org/gallery/album/entire/npp/all/hires/true/ . 这些缩略图由一家公司托管,该公司声称专门从事高带宽应用程序的低延迟。

    墙壁时间是:

    一个线程占用4:48--0个超时
    2个线程占用2:38--0个超时
    5个线程占用2:22--20个超时
    10个线程占用2:27--40个超时
    50个线程占用2:27--170个超时

    在最坏的情况下(50个线程),客户端占用的CPU时间少于2秒。

    平均文件大小1.7k
    平均rtt 100 ms(由ping测量)
    平均cli cpu/img 1 ms

    最快的平均下载速度是5个线程,总速度约为15kb/s。

    服务器实际上似乎具有相当低的延迟,因为获取每个图像只需218毫秒,这意味着服务器处理每个请求平均只需18毫秒:

    0 cli发送syn
    50 SRV RCV同步
    50 srv发送syn+ack
    100个cli conn已建立/cli发送get
    150 SRV接收
    168srv读取文件,发送数据,调用关闭
    218 cli recv http headers+两段完整文件mss==1448

    我可以看到,每个文件的平均下载速度很低,因为连接设置的文件大小较小,每个文件的成本相对较高。

    我不明白的是,除了两个线程之外,我几乎看不到性能的改善。服务器似乎足够快,但已经开始在5个线程上超时连接。

    无论是5个线程还是50个线程,超时似乎都是在900-1000个成功连接之后开始的,我认为这可能是服务器上的某种限制阈值,但我预计10个线程仍将明显快于2个线程。

    我是不是丢了什么东西?

    编辑1

    为了便于比较,我安装了downthemall firefox扩展并使用它下载了图像。我将其设置为4个同时连接,超时10秒。DTM花了大约3分钟的时间下载所有文件并将其写入磁盘,而且在大约900个连接之后,DTM也开始出现超时。

    我将运行tcpdump来尝试更好地了解tcp协议级别的情况。

    我还清除了firefox的缓存并点击reload。40秒重新加载页面和所有图像。这看起来太快了——也许火狐把它们放在了一个没有清除的内存缓存中?所以我打开了歌剧,也花了大约40秒。我认为它们的速度更快,因为它们必须使用http/1.1管道?

    答案是!???

    因此,在通过管道测试和编写代码以重用套接字之后,我发现了一些有趣的信息。

    当以5个线程运行时,非流水线版本在77秒内检索前1026个映像,但检索其余290个映像需要65秒。这几乎证实了 MattH's 关于我的当事人被 SYN FLOOD 导致服务器在短时间内停止响应我的连接尝试的事件。但是,这只是问题的一部分,因为77秒对于5个线程获取1026个图像仍然非常慢;如果删除 合成洪水 问题检索所有文件仍需要大约99秒。所以基于一点研究和一些 tcpdump 问题的另一部分似乎是延迟和连接设置开销。

    这里我们回到寻找“最佳点”或最佳线程数的问题。我修改了客户端以实现http/1.1管道,发现在这种情况下,最佳线程数在15到20之间。例如:

    1线程占用2:37--0个超时
    2个线程占用1:22--0个超时
    5个线程占用0:34--0个超时
    10个线程占用0:20--0个超时
    11个线程占用0:19--0个超时
    15个线程占用0:16--0个超时

    有四个因素 影响;延迟/rtt、最大端到端带宽、recv缓冲区大小 以及正在下载的图像文件的大小。 See this site for a discussion on how receive buffer size and RTT latency affect available bandwidth .

    除上述之外,平均文件大小还影响每个连接的最大值 传输速率。每次发出get请求时,都会在 你的传输管是连接RTT的尺寸。例如,如果 最大可能传输速率(recv buff size/rtt)为2.5mbit,并且 你的rtt是100ms,那么每个get请求在你的 管子。对于平均大小为320kb的大型图像,这相当于10%的开销 每个文件,有效地将可用带宽减少到2.25mbit。然而, 对于3.2kb的小平均文件大小,开销会跳到1000%,并且 可用带宽减少到232 kbit/秒-大约29 kb。

    因此,要找到最佳线程数:

    间隙尺寸=MPTR*RTT
    mptr/(mptr/gap size+avg file size)*平均文件大小)

    对于我上面的场景,这给了我11个线程的最佳线程数,这与我的实际结果非常接近。

    如果实际连接速度低于理论mptr,则 应改为在计算中使用。

    1 回复  |  直到 14 年前
        1
  •  7
  •   MattH    14 年前

    请更正此摘要不正确:

    • 你的 multi-threaded 客户端将启动一个连接到服务器的线程,并只发出一个 HTTP GET 然后那根线就闭合了。
    • 当你说1,2,5,10,50个线程时,你只是指你允许多少个并发线程,每个线程本身只处理一个请求
    • 您的客户端需要2到5分钟下载1000多个图像
    • Firefox和Opera将在40秒内下载等效的数据集

    我建议服务器速率限制http连接,可以通过webserver守护进程本身、服务器本地防火墙或最有可能的专用防火墙。

    您实际上是在滥用webservice,因为没有对多个请求重新使用http连接,而您遇到的超时是因为 SYN FLOOD 被夹住了。

    Firefox和Opera可能使用4到8个连接来下载所有文件。

    如果重新设计代码以重用连接,则应获得类似的性能。