关于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

相关文章
相关标签/搜索