Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何正确使用线程连接ping url?_Ruby_Multithreading - Fatal编程技术网

Ruby 如何正确使用线程连接ping url?

Ruby 如何正确使用线程连接ping url?,ruby,multithreading,Ruby,Multithreading,我正在尝试ping大量url并检索有关url证书的信息。正如我在这篇thoughtbot和其他文章中所读到的,我已经读到最好的方法是使用线程。然而,当我实现线程时,我不断遇到超时错误和其他URL问题,我可以自己成功地检索这些URL。我在另一个相关问题中被告知,我之前问过,我不应该对线程使用超时。但是,我在超时块中看到的示例包装API/NET::HTTP/TCPSocket调用,并且基于我所读到的opn,整个API/NET::HTTP/TCP套接字调用将嵌套在线程中。这是我的密码: class S

我正在尝试ping大量url并检索有关url证书的信息。正如我在这篇thoughtbot和其他文章中所读到的,我已经读到最好的方法是使用线程。然而,当我实现线程时,我不断遇到超时错误和其他URL问题,我可以自己成功地检索这些URL。我在另一个相关问题中被告知,我之前问过,我不应该对线程使用超时。但是,我在超时块中看到的示例包装API/NET::HTTP/TCPSocket调用,并且基于我所读到的opn,整个API/NET::HTTP/TCP套接字调用将嵌套在线程中。这是我的密码:

class SslClient
  attr_reader :url, :port, :timeout

  def initialize(url, port = '443', timeout = 30)
    @url = url
    @port = port
    @timeout = timeout
  end

  def ping_for_certificate_info
    context = OpenSSL::SSL::SSLContext.new
    certificates = nil
    verify_result = nil
    Timeout.timeout(timeout) do
      tcp_client = TCPSocket.new(url, port)
      ssl_client = OpenSSL::SSL::SSLSocket.new tcp_client, context
      ssl_client.hostname = url
      ssl_client.sync_close = true
      ssl_client.connect
      certificates = ssl_client.peer_cert_chain
      verify_result = ssl_client.verify_result
      tcp_client.close
    end
    {certificate: certificates.first, verify_result: verify_result }
  rescue => error
    puts url
    puts error.inspect
  end
end

  [VERY LARGE LIST OF URLS].map do |url|
      Thread.new do
        ssl_client = SslClient.new(url)
        cert_info = ssl_client.ping_for_certificate_info
        puts cert_info
      end
    end.map(&:value)

如果您在终端中运行此代码,您将看到许多超时错误和ERNNO:TIMEDOUT错误,这些错误适用于fandango.com、fandom.com、mcaffee.com、google.de等应该返回信息的站点。然而,当我单独运行这些时,我得到了所需的信息。当我在线程中运行它们时,它们往往会失败,特别是对于具有外来域名的域。我要问的是我是否正确使用了线程。我粘贴的这段代码是与rails中的ActiveRecord对象交互的较大代码片段的一部分,具体取决于给定的结果。我是否正确使用超时和线程?我需要做些什么才能让它工作?为什么ping可以单独工作,但不能用线包裹?非常感谢您的帮助。

有几个问题:

  • 你不会产生数千个线程,使用一个连接池(例如),这样你最多可以有20-30个并发请求(这个最大数量应该通过测试网络性能下降和超时的时间点来确定)
  • 当你使用线程时,很难保证你的代码不会被破坏,这就是为什么我建议你在别人为你找到的地方使用一些东西,比如(有线程安全和并发请求的例子)。还有其他的lib(typhous,patron),但这一个是纯Ruby的,所以基本的线程安全更容易实现
  • 您不应使用
    Timeout
    (请参阅和)。使用
    IO。选择
    或其他内容

此外,我建议您学习线程问题,如死锁、饥饿和所有的陷阱。在您的情况下,由于所有线程都在争夺带宽/网络,您的网络资源非常匮乏。

有几个问题:

  • 你不会产生数千个线程,使用一个连接池(例如),这样你最多可以有20-30个并发请求(这个最大数量应该通过测试网络性能下降和超时的时间点来确定)
  • 当你使用线程时,很难保证你的代码不会被破坏,这就是为什么我建议你在别人为你找到的地方使用一些东西,比如(有线程安全和并发请求的例子)。还有其他的lib(typhous,patron),但这一个是纯Ruby的,所以基本的线程安全更容易实现
  • 您不应使用
    超时
    (请参阅和)。使用
    IO。选择
    或其他内容

此外,我建议您学习线程问题,如死锁、饥饿和所有的陷阱。在您的情况下,由于所有线程都在争夺带宽/网络,您的网络资源非常匮乏。

同时创建多个操作系统线程将导致它们都在争夺资源,从而导致您正在经历的超时。我“我不是一个真正喜欢Ruby的人,但每个线程都是一个操作系统线程,需要一定的内存和cpu时间,而你的大多数线程都会坐在那里,摆弄着大拇指,等待ping返回,但仍然占用内存和cpu。更成功的web服务器使用异步通信,甚至像Erlang这样的轻量级线程。另外,我听说NODE.JS非常成功。模仿他们所做的事。使用;不要只创建一千个并发线程。对于像连接到URL这样需要大量等待的事情,您可以超额订阅每个CPU核心的线程数,但数量不会很大。你得做个实验。很久以前我做过类似的事情,我也做过。也许会有帮助。谢谢你们的评论。嘿@anothermh你有没有关于泳池实验的建议?我看到过一些s.o.问题,比如这个问题,50是连接池的起点,然后是5个线程,等等。什么决定了连接池的大小?在试验时我需要/寻找什么?您不需要连接池。你只需要一个线程池。什么决定了线程池的大小?CPU核心计数和IO等待时间。1 CPU核心=1个线程(通常),但由于连接到URL需要大量等待,因此每个CPU可以运行多个线程。还要等多久?如果它们是本地网络上的主机,则不会太多。如果他们在互联网上,会有更多,但这也要视情况而定。这就是为什么你必须进行实验;用于找到最佳点。一次创建多个操作系统线程将导致它们争夺资源,从而导致您遇到的超时。我“我不是一个真正喜欢Ruby的人,但每个线程都是一个操作系统线程,需要一定的内存和cpu时间,而你的大多数线程都会坐在那里,摆弄着大拇指,等待ping返回,但仍然占用内存和cpu。更成功的web服务器使用异步通信,甚至像Erlang这样的轻量级线程。另外,我听说NODE.JS非常成功。模仿他们所做的事。使用;不要只创建一千个并发线程。对于像连接到URL这样需要大量等待的事情,您可以超额订阅每个CPU核心的线程数,但数量不会很大。你得做个实验。我以前也做过类似的实验