2013-12-13 93 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