那我就來繼續隨便談談twisted
首先討論一下, 為什麼需要twisted, 需要非同步
為了更高效的利用cpu和資源, 提高使用者的相應速度
任務需要較長時間才能完成分成兩種情況,
1) 計算量較大, 需要cpu算好久才能算出來, 自然算出來才能給結果, 稱為cpu等待.
2) 需要等待其他的資料, 比如需要從伺服器等待獲取資訊, 需要從資料庫等待查詢結果, 這種雖然自己很閒, 無事可做, 但不得不幹等, 稱為i/o等待.
cpu等待是沒辦法的, 就是要算那麼長時間, 唯一能做的是為了讓使用者體驗好些, 大家輪流占用cpu, 這種典型的方法就是多執行緒...
i/o等待是應該需要優化的, 這是幹等白白浪費並佔住了資源, 使得其他使用者也無法使用. 這兒就需要非同步, 需要twisted, 需要callback.
本來我要等待資料, 然後程式才能繼續, 非同步的做法是, 把後續的處理程式封裝成callback, errback, 把等待資料ready封裝成event (讓系統呼叫select去偵聽資料i/o). 這樣主程式不需要去專門等待某乙個event, 有event觸發就處理, 這就達到非同步的效果.
所以在判斷是否需要使用非同步, 該不該使用twisted時, 只需要考慮是否存在i/o等待, 只要有i/o等待就應該考慮使用非同步.
而twisted的**無論多麼複雜, 其實都是在做如下這樣簡單的事情,
通過定義protocal和factory來解析請求
通過定義callback來處理請求
定義i/o connection (將factory作為引數, 包含protocal和callback), 並加到event loop(reactor)中去
run reactor
再來, twisted主要應用於什麼場景, 使用twisted真的比直接使用socket方便合理嗎
twisted主要用於開發server, 它就是為此而生的
下面我們通過簡單的例子來和socket對比一下,
下面我們先來看一下客戶端, 建立乙個鏈結, 傳送多條message
sock = socket.socket(socket.af_inet, socket.sock_stream)sock.connect((ip, port))
sock.send('hello world1')
time.sleep(3)
sock.send('hello world2')
time.sleep(3)
sock.send('hello world3')
sock.close()
先來看看socket的server, 顯然這段**只能接收到第一條message
如果需要接受所有的message, 必須在conn.recv前加上while, 這樣保證接收到所有message後才去accept新的connection.
如果同時開啟多個client, 那麼這兒必須先接收完第乙個client的所有message, 才能開始接收第二個client的...
這樣就block了, 使用者就不爽了...
sock = socket.socket(socket.af_inet, socket.sock_stream)sock.setsockopt(socket.sol_socket, socket.so_reuseaddr, 1)
sock.bind(('localhost', 3000))
sock.listen(5)
while true:
conn, addr = sock.accept()
buf = conn.recv(1024)
print 'recv data:' + buf + '\n'
再來看看用twisted實現的server, 可以試試同時開啟多個上面的client, 該server是可以同時併發接收每個client的資料的, 而不是需要處理完乙個client, 才開始處理下乙個. 所以確實用twisted開發server比直接使用socket方便合理許多.
from twisted.internet import protocol, reactorfrom twisted.internet.protocol import factory
class echo(protocol.protocol):
def connectionmade(self):
self.factory.numprotocols = self.factory.numprotocols+1
print 'connectionmade'
print 'numprotocols:'+ str(self.factory.numprotocols)
def connectionlost(self, reason):
self.factory.numprotocols = self.factory.numprotocols-1
print 'connectionlost'
print 'numprotocols:'+ str(self.factory.numprotocols)
def datareceived(self, data):
#self.transport.write(data)
print 'datareceived:' + str(data)
myfactory = factory()
myfactory.protocol = echo
myfactory.numprotocols = 0
reactor.listentcp(3000, myfactory)
reactor.run()
想想twisted是怎麼樣實現這種非同步的, 是怎麼樣儲存各個connection並在之間自由切換的?
從頭開始, 大家先簡單把i/o想象成檔案, 對於作業系統而言, i/o操作就等同於對檔案的讀寫操作, 其他對系統是透明的.
對於乙個twisted server, 剛開始監聽乙個i/o埠(這兒可以想象對於twisted有個偵聽佇列, 剛開始list中只有乙個port), 等待請求...
請求到達(相當於conn, addr = sock.accept() ), 觸發connectionmade event, 並把該connection加到偵聽佇列.
某connection收到資料, 觸發datareceived event
某connection closed, 觸發connectionlost event, 並把該connection從偵聽佇列中刪除.
如果在某個callback, 如datareceived**現乙個很耗時的任務時該怎麼辦, 比如需要從另外乙個伺服器獲取資料.
非同步中, callback使用的第一原則是, 不能block, 因為主線程一旦block, 啥事就都做不了
所以這兒必須要再次使用非同步, 在callback中再次設定event和callback, 並將和遠端伺服器的connection加到偵聽佇列中.
繼續談談Twisted
那我就來繼續隨便談談twisted 首先討論一下,為什麼需要twisted,需要非同步 為了更高效的利用cpu和資源,提高使用者的相應速度 任務需要較長時間才能完成分成兩種情況,1 計算量較大,需要cpu算好久才能算出來,自然算出來才能給結果,稱為cpu等待.2 需要等待其他的資料,比如需要從伺服器...
Twisted基本模型
twisted 網路程式設計框架是一種基於事件的網路程式設計框架,使用者需要繼承特定的類,並過載其中的方法來處理網路通訊 中可能出現的各種情況。twisted的網路通訊模型 最基本的也要由三部分組成 反應器 reactor 協議 protocol 工廠 factory 1 其中反應器reactor用...
Twisted基本模型
一 twisted基本模型 twisted 網路程式設計框架是一種基於事件的網路程式設計框架,使用者需要繼承特定的類,並過載其中的方法來處理網路通訊 中可能出現的各種情況。twisted的網路通訊模型 最基本的也要由三部分組成 反應器 reactor 協議 protocol 工廠 factory 1...