我正在开发一个 Ruby 脚本,它将open-uri
向各种 API 发出数百个网络请求(通过),我想并行执行此操作,因为每个请求都很慢且阻塞。
我一直在考虑使用Thread
或Process
实现这一点,但我不确定使用哪种方法。
关于网络请求,我什么时候应该使用Thread
over Process
,还是没关系?
我正在开发一个 Ruby 脚本,它将open-uri
向各种 API 发出数百个网络请求(通过),我想并行执行此操作,因为每个请求都很慢且阻塞。
我一直在考虑使用Thread
或Process
实现这一点,但我不确定使用哪种方法。
关于网络请求,我什么时候应该使用Thread
over Process
,还是没关系?
在详细介绍之前,已经有一个库可以解决您的问题。Typhoeus针对并行运行大量 HTTP 请求进行了优化,并且基于 libcurl 库。
就像拥有 100 个蛇头的神话野兽的现代代码版本一样,Typhoeus并行运行 HTTP 请求,同时干净地封装了处理逻辑。
线程将在与您的应用程序相同的进程中运行。由于 Ruby 1.9 原生线程被用作底层实现。资源可以很容易地跨线程共享,因为它们都可以访问应用程序的相互状态。然而,问题是您无法在大多数 Ruby 实现中使用 CPU 的多核。
Ruby 使用全局解释器锁 (GIL)。GIL 是一种锁定机制,可确保相互状态不会因来自不同线程的并行修改而损坏。JRuby、Rubinius 或 MacRuby 等其他 Ruby 实现提供了一种没有 GIL 的方法。
进程彼此分开运行。进程不共享资源,这意味着每个进程都有自己的状态。如果您想跨请求共享数据,这可能是一个问题。一个进程也分配它自己的内存栈。您仍然可以使用 RabitMQ 之类的消息传递总线来共享数据。
我不建议仅使用线程或仅使用进程。如果你想自己实现,你应该同时使用两者。为每n 个 请求分叉一个新进程,然后再次生成多个线程来发出 HTTP 请求。为什么?
如果您为每个 HTTP 请求分叉另一个进程,这将导致进程过多。尽管您的操作系统可能能够处理这个问题,但开销仍然是巨大的。一些 HTTP 请求可能会很快完成,所以为什么要费心额外的进程,只需在另一个线程中运行它们。