2013-12-13 75 views
5

当前状况: 我有一个Ra应用程序,带有N个延迟的工作人员。无论何时我想向某台机器发送SSH请求,我都会为该工作人员创建一个任务。工人执行类似的操作:Rails +延迟作业:SSH连接池

Net:SSH.start(hostname, username, :password => pass) do |ssh| 
    ssh.exec!(command) 
end 

有时候我会创建例如50个这样的任务要一一执行,或者在5-10分钟之内完成。在这种情况下,每个任务都会打开单独的连接,但这种连接无效,有时由于连接太多而被目标服务器阻止。

我想要什么:已打开连接存储在某处并被每个工作人员重新使用。所以每个工人获得连接不知何故,然后只需运行

ssh.exec!(command) 

我已经试过

  • 存储在文件/数据库连接/缓存看起来是因为它们不是序列化不可能
  • 已尝试使用初始化器下实例化的全局变量的单例类。然而,每个工作者的类对象是不同的(后来发现全局变量不能作为选项)。

有没有办法解决这个问题?任何其他想法?谢谢!!

+0

你的任务是否持续了一段时间,还是你只是不同步SSH任务? –

+0

任务实际上并未延迟,但更像是排队。例如,有一个操作A,在这个操作中,执行一堆ssh命令,然后执行任务B(5-10分钟),然后执行任务C(再次执行ssh请求) –

回答

3

首先一些基本知识;一个SSH连接的核心是一个到远程机器的低级套接字连接。套接字不能(容易地)在进程之间共享。因此,在多个进程上运行的东西不能共享相同的SSH连接。

接下来,您需要知道当前设置中的哪些部分在单独的进程中运行。我们得到的是:

  1. Rails是在大多数情况下,基于过程:在单独的进程中运行独立的Web请求。因此,将SSH连接存储在Rails应用程序中并不是一个可靠的解决方案。

  2. 就我所知,延迟工作也是基于流程的。主进程启动从进程来处理每个作业。因此,DJ也不适用于此目的。

你需要的是一个主进程存储的SSH会话(一个或多个),然后等待那些这就需要在您的SSH远程机器的一个执行的命令传入消息。

就我个人而言,我只是编写一个简单的线程Ruby守护进程来处理这个任务。如果您不想直接处理套接字编程,则可以使用EventMachine之类的函数来处理通信和处理。

如果你不舒服或EventMachine的套接字编程,那么你可以看一些消息系统,如RabbitMQ,或 ZeroMQ与创建您的客户端和服务器。

我还发现了一些名为ActiveMessaging的Rails,但我不确定该项目的当前和工作方式。

但就像我说的,我认为最简单的实现只是一个套接字守护进程,它在后台运行并跟踪开放的SSH连接,然后监听来自Rails应用的命令。

请记住,如果你实现类似的东西,还要考虑安全考虑。否则,您可以通过守护进程轻松让任何人通过SSH访问所有远程计算机。

编辑

一个更简单的想法:

只要有一个守护进程定期从您的Rails应用程序从数据库中读取表的命令。然后这个守护进程可以根据它在这个“作业队列”表中找到的内容执行这些命令。这样你就不必处理套接字通信了,这个解决方案就是一个轮询解决方案。

+0

非常感谢,这非常有用!我想过有一个单独的过程,但是这可能会成为我的应用程序的一个瓶颈(因为有N个DJ工作人员发送N * X个请求,现在只需要一个过程)。然而,看起来我没有别的选择。无论如何,非常感谢! –

+0

是的,我想在一个单独的数据库表中的任务:)这将是一个延迟工作机制的模拟,我基本上必须写“工人”它..这看起来有点开销我猜 –

+0

@AndreySereda只是守护进程会为每个需要执行的命令启动一个线程。您可以更进一步,通过启动每个拥有自己的一组SSH连接池的1-N进程来实现某种负载平衡。在这种情况下,RabbitMQ或ZeroMQ可能会提供更好的体系结构。无论如何,我认为你应该能够使它工作,甚至可以通过一点额外的脑力工作来扩展它:) – Casper