關於gevent的一點總結

0x00 基本概念

gevent是基於libev和greenlet的一個python異步框架。python

libev是一個高性能的事件循環(event loop)實現。
事件循環(也稱做IO多路複用),是解決阻塞問題,實現併發的一種方法。簡單點說,就是event loop會捕獲、處理io事件的變化:遇到阻塞,就跳出;阻塞結束,就繼續。這依賴於系統底層的select函數及其升級版:pollepoll。《深刻理解計算機系統》一書中,對此有深刻探討。git

greenlet是一個python的協程管理、切換模塊。經過greenlet,你能夠顯式地在不一樣的任務之間切換。github

0x01 Actor模式

ActorErlang語言的精髓。它強調基於消息傳遞的併發機制。
咱們模仿這篇文章 創建一個actor模型。核心代碼以下:併發

import genvet
# 主隊列
queue = gevent.queue.JoinableQueue()
while True:
    # 持續獲取數據
    try:
        data = queue.get(timeout=5)
    except Empty:
        gevent.sleep(0.5)
        continue
    # 交付給Actor
    if data:
        gl = Actor(data)
        g1.start()
        g1.join()

Actor爲咱們自定義的一個Greenlet的子類,核心代碼以下:框架

class Actor(Greenlet):
    def __init__(self, data):
        self.data = data
        Greenlet.__init__(self)
    
    def _run(self):
        result = do_something(self.data)
        return result

這樣,咱們這個Actor能夠從消息隊列中接受數據,經過start()_run()被調用。異步

因爲geventmonkey patch的存在,你基本能夠以同步的方式,寫出異步的代碼。這樣的寫法顯得不少餘。可是,卻能夠很好的實現業務的分離,讓代碼更清晰,更容易維護和擴展。函數

0x02 實現回調

若是你還但願給Actor加一個回調。即等他完成了以後,再進行某些處理。
那咱們能夠對Actor機型以下修改:oop

class Actor(Greenlet):
    def __init__(self, data):
        self.data = data
        Greenlet.__init__(self)
    
    def _run(self):
        # 經過self.link添加回調函數。
        self.link(callback)
        result = do_something(self.data)
        return result

你能夠經過Greenlet().link(),給你的協程添加一個回調。這個回調函數只接收一個參數,即這個協程的實例(g1)。咱們會看到_run()函數,實際上是返回了一個結果result的。那咱們在回調函數中可否取得這個值呢。實際上是能夠的,這個值被存在了g1.value中。性能

仍是那句話,這樣的設計,可能看起來不少餘。但隨着框架功能的增長,這樣多餘的設計會讓你的代碼,愈發地靈活。.net

相關文章
相關標籤/搜索