2013-02-13 67 views
1

許多(> 1000)的工人(過程)做一些和想要保存在數據庫中的工作成果。工作結果是JSON對象。工人每秒產生1-5個JSON對象。數據庫保存程序是分開的過程。從工作者到保護者傳輸JSON對象的單向連接是multiprocessing.Pipe。管道數量等於工人數量。處理超出範圍選擇

在保護過程中定期сall:

def recv_data(self): 
    data = [] 
    for pipe in self.data_pipe_pool: 
     if pipe.poll(): 
      data.append(pipe.recv()) 
    return data 

self.data_pipe_pool - 從管道的工人名單。

所有的工作,如果我跑〜100名工人。如果我運行> 1000工人,我得到異常:

2013-02-13T15:17:40.731429 
Traceback (most recent call last): 
    File "saver.py", line 44, in run 
    profile = self.poll_data() 
    File "saver.py", line 116, in poll_data 
    ret = self.recv_data() 
    File "saver_unit.py", line 127, in recv_data 
    if pipe.poll(): 
IOError: handle out of range in select() 

我知道,這是由於與select()通話和:

FD_SETSIZE通常是在GNU/Linux系統定義爲1024

但是那裏叫select?如果在pipe.poll()中,爲什麼我超過了FD_SETSIZE限制,我打電話pipe.poll()單個管道?我在哪裏可以通過這個電話select來觀看Python語言資源?

什麼解決辦法不超過FD_SETSIZE限制或不使用select

回答

2

如果您檢查select manual page,你會發現:

與FD的值是負值或等於或大於FD_SETSIZE會導致不確定的行爲執行FD_CLR()或FD_SET() 。

這意味着,如果使用select幕後在poll調用(很可能),你有文件描述符大於FD_SETSIZE(很可能,如果你有超過1000個管道),那麼結果可能是什麼。

+0

感謝您的回答。 如何避免陰影調用'select'?可能是存在管道(或over object)epoll API在低級別? – sheh 2013-02-13 15:05:01

0

你有沒有想過使用類似beanstalkd的東西,因爲它聽起來像你有一個管道從工人到服務器,而通常你會有1000名工人,然後從結果隊列中讀取10個服務器來存儲它們在數據庫中。

的好處是,它很可能是你的工人正在採取更多的時間做他們的工作比談話的服務器,但你得開到該服務器的管道。

你可以有一個「工作隊列」,工人的您1000年從採取和「結果隊列」,它們存儲在結果。此後,您可以將許多服務器從「結果隊列」中取出以存儲在數據庫中。

這是說:「至少,那麼你會不會文件句柄用完了」很長的路要走。

0

我使用epoll解決了這個問題。解決方法很簡單:

def set_data_pipe_poll(self, data_pipe_poll): 
    self.epoll = select.epoll() 
    for p in data_pipe_poll: 
     self.epoll.register(p, select.EPOLLIN) 
    self.data_pipe_poll = data_pipe_poll 

def recv_data(self): 
    data = [] 
    events = self.epoll.poll(timeout = 0) 
    for fileno, _ in events: 
     p = filter(lambda x: x.fileno() == fileno, self.data_pipe_poll)[0] 
     data.append(p.recv()) 
    return data 

當我打電話epoll.poll()我不叫select

0

我有類似的問題。我爲每個工人使用multiprocessing.Queue,當工人數量大約爲600時,排隊方法失敗,IOError: handle out of range in select()。我發現issue在導致問題的官方bug跟蹤器中。它被固定在2.7.4(我有2.7.3)。 python包的更新解決了這個問題。