2017-02-13 71 views
0

假設我們有這是一個事件驅動單線程服務器上承載的WSGI應用:Eventlet在請求WSGI服務器和耗時的操作

from eventlet import wsgi 
import eventlet 

def app(env, start_response): 
    # IO opeartions here 
    ... 

wsgi.server(eventlet.listen(('', 8090)), app) 

在應用程序的功能,一些I/O操作,因爲必須執行讀取文件或數據庫訪問。

現在,當我們在應用程序中執行IO操作時,服務器被有效阻止,無法爲其他客戶端提供服務。

問:什麼是可能的解決方案來解決這個問題?我怎樣才能讓Eventlet wsgi服務器執行耗時的操作而不被阻塞?

回答

0

TL; DR:使用mysqldb/psycopg或eventlet.import_patched() pure python DB驅動程序; tpool.execute()文件和其他一切。

試着將您的思維過程修復爲可以轉換爲與Eventlet合作的分離操作以及不可能的操作。這裏的合作意味着打破「執行代碼」 - 「等待結果」部分,並在結果準備好時提供通知機制。 Eventlet的主要通知機制是文件描述符。

因此,等待文件描述符的所有內容都是候選爲綠色(而不是阻塞)。最重要的是,它會影響所有網絡IO。如果您的阻塞函數是用純Python編寫的,只需使用import_patched(module_name)修改其socket和其他對Eventlet綠色版本的引用。 mysqldbpsycopg2是C擴展模塊合作的特例,感謝作者的明確支持。其他的一切都在非Python代碼中阻塞 - 您的選擇是操作系統線程。

不幸的是,等待實際的磁盤文件充滿了怪癖,所以我建議使用操作系統線程,並且我們有內置的線程池來支持它。將blocking_fun(filepath, something_else)轉換爲eventlet.tpool.execute(blocking_fun, filepath, something_else)並且不會阻止所有操作。詳細信息請查看tpool文檔。

如果可以,將整個應用程序重新設計成阻塞和非阻塞過程,並讓它們通過套接字進行通信。從代碼重寫的角度來看這很難,但對於運行時,調試非常簡單;強大且防故障的設計。

相關問題