并发SOAP api请求共同占用更长的时间

时间:2013-07-11 10:53:14

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2

我正在使用savon gem与soap api进行交互。我正在尝试使用parallel gem向api发送三个并行请求。通常每个请求大约需要13秒才能完成,因此对于三个请求大约需要39秒。在使用并行gem并使用3个线程发送三个并行请求之后,需要大约23秒来完成所有三个请求,这非常好但我无法弄清楚为什么它没有在14-15秒内完成它。我真的需要降低总时间,因为它会直接影响我网站的响应时间。关于它为什么会发生的任何想法?网络请求本质上是阻塞的吗?

我发送请求如下

Parallel.map(["GDSSpecialReturn", "Normal", "LCCSpecialReturn"], :in_threads => 3){ |promo_plan| self.search_request(promo_plan) }

我尝试过使用多个进程但没有用。

2 个答案:

答案 0 :(得分:3)

我有两个理论:

  • 部分工作负载无法并行运行,因此您看不到3倍的加速,但略低于此。很难看到多线程任务与所使用的CPU数量成比例地加速100%,因为总有一些位必须一次运行一个。请参阅Amdahl's Law,其中提供了描述此问题的公式,并说明:
  

在并行计算中使用多个处理器的程序的加速受到程序序列部分所需时间的限制

  • 涉及磁盘I / O,由于磁盘搜索时间,并行运行较慢,限制了每秒IO。请记住,除非您使用的是SSD,否则每次查找不同的内容时,磁盘都必须进行物理旋转。一次有3个请求,磁盘反复跳过磁盘,试图在3个不同的地方完成I / O请求。这就是硬盘驱动器上的随机I / O比顺序I / O慢的原因。即使在SSD上,随机I / O也会慢一些,尤其是涉及小块读写时。

我认为如果你在同一个系统上运行你的数据库,选项2就是罪魁祸首。问题是,当SOAP调用命中DB时,它会受到这两个因素的影响。即使是速度极快的15000 RPM服务器硬盘也只能每秒管理约200次IO操作。 SSD将达到10,000-100,000 + IO / s。 See figures on Wikipedia for ballparks.但是,大多数数据库都会进行一些聪明的内存缓存来缓解这些问题。

一种聪明的方法来测试它是否是因子2是运行H2 Database内存数据库并使用它来测试SOAP调用。它们的完成速度要快得多,可能和你一样应该一次看到1,3或$ CPU-COUNT个请求的类似执行时间。

答案 1 :(得分:1)

这实际上是个大问题,这取决于很多因素。

1。 Ruby语言实现

MRI,Rubinus,JRuby可能有所不同。所以我不确定是否是平行宝石  支持Rubinus和JRuby。

2。你的机器

您的计算机中有多少CPU核心,您可以使用并行流程来利用它?如果您有多个核心,您是否尝试过使用过程?

Parallel.map(["GDSSpecialReturn", "Normal", "LCCSpecialReturn"]){ |promo_plan| self.search_request(promo_plan) } # by default it will use [number] of processes if you have [number] of CPUs

3。下划线self.search_request发生了什么?

如果你在MRI环境中运行它,导致GIL,它实际上运行你的代码不同时。或者准确地说,IO呼叫不会阻塞(MRI实施),因此只有网络呼叫部分将同时运行 ,而不是所有其他部分。这就是为什么我对你在 self.search_request 中所做的其他工作感兴趣,因为这会对整体性能产生影响。


所以我建议你可以在不同的环境和不同的机器上测试你的代码(在本地机器和真实的生产机器之间可能会有所不同,所以请尝试调整和基准测试)以获得最佳结果。

顺便说一句,如果你想了解更多关于ruby中的线程/进程的信息,强烈推荐Jesse StorimerWorking with ruby threads,他做了很好的解释所有这些事情。

希望它有所帮助,谢谢。