eventlet implementation explained 1

Eventlet is an asynchronouse I/O library which is based on greenlet. We can write very efficient network programms with eventlet without using threads. So let’s see how it is implemented. We start from an echo server example which you can find in eventlet.

#! /usr/bin/env python
"""/
Simple server that listens on port 6000 and echos back every input to
the client.  To try out the server, start it up by running this file.

Connect to it with:
  telnet localhost 6000

You terminate your connection by terminating telnet (typically Ctrl-]
and then 'quit')
"""

import eventlet

def handle(fd):
    print "client connected"
    while True:
        # pass through every non-eof line
        x = fd.readline()
        if not x: break
        fd.write(x)
        fd.flush()
        print "echoed", x,
    print "client disconnected"

print "server socket listening on port 6000"
server = eventlet.listen(('0.0.0.0', 6000))
pool = eventlet.GreenPool()
while True:
    try:
        new_sock, address = server.accept()
        pool.spawn_n(handle, new_sock.makefile('rw'))
    except (SystemExit, KeyboardInterrupt):
        break

At first look, everything seems to be blocking. But note that no standard library is explicitly imported, the socket we use is provided by eventlet, which is non-blocking by default.

We need to launch a debugger (I use spe with winpdb) to see what really happens insided eventlet. Let me present you the stack trace.

socket.accept
    socket_accept(fd)
        py.socket.accept # standard api is called
            return None for non-blocking if no incoming connection
            return Not None if has incoming connection
        trampoline # if no incomming connection
            hub.add # add a FdListener
                add the listener to the queue correponding the fd(socket)
                callback of the listener is greenlet.current.switch which is the main thread
            hub.switch
                hub.greenlet.switch # run = hub.run (hub -> BaseHub
                    BaseHub.run # main loop, this is a greenlet
                        prepare_timers # sort timers
                        fire_timers    # fire timers with current tick
                        prepare_timers # why ???
                        wait # wait a period of timer
                            py.select.select # wait
                            if has avail readers
                                FdListeners[0](fd) # notify the listerner, read/write can be performed without blocking,
                                                   # callback is to switch to trampoline
            hub.remove # remove a listener, we reach here if there're some read/write events

If there’s no incoming connection, trampoline is called. This function is very important to eventlet, such as accept, recv, readline will call this function inside. Within trampoline, a listener is added to a the hub which is the core of eventlet. When there’s any read/write events, corresponding listeners will be called, so that we can at on the events. The callback of listeners are greenlet which by default are the main greenlet. In this example, if there’s a client connecting to the server, a listerner is notified. Remember that the callback of a listener is a greenlet, which is by default the main greenlet, this means that we will switch back to trampoline, and then return to our main loop to spawn a new handler.

Now we are spawning a handler, below is the stack trace of spawn_n.

GreenPool.spawn_n
    greenthread.spawn_n
        _spawn_n # create a greenlet of the client handler
        hub.schedule_call_global # create a corresponding timer, and then add the timer to a list which is a priority queue.

GreenPool.spawn_n just creates a timer which will be process when accept is called in the next loop run. The timer contains a greenlet which wraps our handle function.

In next loop, server.accept is called again. Assume that there’s no new incoming connection, trampoline is called and we will switch to the main loop. Timers will be processed, our handle function is called. If there’s no recving data, we then switching to the main loop.

It’s a bit complex, since the control flow is not linear. After you have a basic grasp of what’s going on, you will be fine.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值