我們有一個Django webapp,它使用Celery 4.x異步運行任務。主要任務需要Django/Celery代碼與20-100臺其他服務器執行網絡通信操作。我們發送給這些其他服務器的每個請求都是相同的,即用戶向Django發送一條命令,然後告訴Celery向20-100臺其他服務器發送完全相同的命令。問題在於,對於Celery的基本配置,如果我們有4名員工,那麼Celery將只與4臺服務器通信。爲了解決這個問題,我們試着用gevent和芹菜一起使用。然而,gevent使用的是協程而不是完整的線程,而對於我們的網絡操作,我們使用我們自己的用C編寫的python模塊。換句話說,我們不使用可以被修補的python套接字或請求模塊。Django plus Celery/RabbitMQ帶有用於C插座模塊的線程
所以,我們想要做的是以下幾點。爲了爭論,讓我們說我們的C通信模塊被稱爲「cnet」。如果我們有,我們必須與之通信20臺其他服務器,我們將有一個芹菜任務函數,它是這樣的:
# This uses our cnet module (written in C) to connect to a single other server
def connect_to_server(server, user_data):
response=cnet.execute_request(server,user_data)
output=do_something_with_response(response)
return output
@task
def send_something_important_to_all_servers(dest_servers, user_data):
for server in dest_servers:
t = create new thread to run connect_to_server(server, user_data)
t.start()
wait/join on all threads
return
我對我們如何能實現這樣的一些問題。最初我們使用prefork池和多個工人,每個工人一個任務,但沒有擴展。接下來我們使用了gevent,但我們沒有做任何特別的事情,只是推出了4名工人的芹菜,每個工人都有大量的greenlet,很像這裏所做的:https://groups.google.com/forum/?fromgroups=#!topic/celery-users/RNZLiNyykQQ 這當然仍然表現出同樣的問題,如果我們有4名工人,我們只有4件東西要同時運行。
現在我已經讀過,我們可以使用eventlet池,並且有一些名爲tpool的東西,我們可以在任務內使用它來產生多個線程。該文檔說,這對於我們使用本地C網絡模塊而不能被猴子修補的情況特別有用。那麼這對我們來說是最好的方法嗎?即用tpool使用eventlet?在我們的情況下,是否有任何理由使用gevent而不是eventlet,如果有的話,是否存在與tpool等價的gevent?有沒有人有處理這種情況的芹菜代碼的例子,即使用非本地網絡代碼,不能被猴子修補?
這時我們不能在C中進行多路複用,在一個非常複雜的C程序中工作太多。我很確定在C代碼中沒有使用python套接字。所以這聽起來像tpool是要走的路。但是,你能幫我理解一下嗎?tpool.execute是否阻止了其它協程的調用,這樣所有調用tpool.execute的協程都可以同時運行(無論如何,最多可以有20個)?這在文檔中沒有很好地解釋。 – Marc
也許沒有使用python套接字,但它是一個簡單的搜索和替換更改。 Tpool的收益與其他一切一樣。 – temoto
gevent中是否有相應的模塊?我可以使用gevent.something而不是使用eventlet.tpool嗎? – Marc