Gevent简介

原创 2016年08月29日 16:18:04

介绍

gevent 是一个python网络框架,对应Java的netty框架,使用greenlet提供异步API,基于libevent ,它为各种并发和网络相关的任务提供了整洁的API.

  • 快速基于libevent的event loop
  • 基于greenlet的轻量级执行单元
  • 重用python标准api(event,queue)
  • 协同的socket和ssl模块
  • 使用标准库和第三方模块写标准阻塞socket(gevent.monkey)
  • dns查询执行通过libevent-dns
  • 基于libevent-http的快速WSGI服务器

安装

=python2.4
greenlet
libevent1.4.x

from gevent import socket

说不能导入socket,参考http://stackoverflow.com/questions/6431096/gevent-does-not-install-properly-on-ubuntu

例子

import gevent
from gevent import socket
urls = ['www.google.com','www.python.org','www.foofish.net']
jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
gevent.joinall(jobs, timeout=2)
print [job.value for job in jobs]

['74.125.128.147', '82.94.164.162', '106.186.27.60']

gevent.socket与python标准库的socket有相同的接口

http://sdiehl.github.io/gevent-tutorial/
http://architects.dzone.com/articles/threads-versus-greenlets
http://blog.pythonisito.com/2012/07/introduction-to-gevent.html

翻译

Gevent简介

官方网站是这么介绍Gevent:

gevent is a coroutine-based Python networking library that uses greenlet to provide a high-level synchronous API on top of the libevent event loop.

简单翻译过来就是:gevent一个基于协程的Python网络库,依赖于libeventevent loop使用greenlet提供高级同步API。

这段话简单描述了gevent的架构实现和技术,不过初学者看了还是一脸茫然。我能想到的能最快让人理解的定义是:

gevent给了你线程,但是没有使用线程

为什么不使用线程

为什么不使用线程呢?线程最大的缺点对我来说就是相比较greenlets(使用在gevent中的类线程的抽象概念)来说它会占用大量资源。 例如:这个模拟helloworld webserver的小程序,下面是没有使用任何并发的代码:

import sys
import socket
import time

def sequential(port):
    s = socket.socket()
    s.bind(('0.0.0.0', port))
    s.listen(500)

    while True:
        cli, addr = s.accept()
        handle_request(cli, time.sleep)

def handle_request(s, sleep):
    try:
        s.recv(1024)
        sleep(0.1)
        s.send('''HTTP/1.0 200 Ok 

HelloWorld''')
        s.shutdown(socket.SHUT_WR)
        print '.',
    except Exception, ex:
        print 'e', ex,
    finally:
        sys.stdout.flush()
        s.close()

if __name__ == '__main__':
    sequential(int(sys.argv[1]))

这段代码使用sleep,目的是是减慢handle_request方法使它更真实。使用Apache的性能测试工具做大并发测试,然而我们得到很糟糕的结果。运行: ab -r -n 200 -c 200 http://lcoalhost:1111/

结果:

Benchmarking localhost (be patient)
Completed 100 requests
apr_pollset_poll: The timeout specified has expired (70007)
Total of 196 requests Completed

到最后超时了。

也许用线程会更好,那么用threads函数替换sequential函数:

import threading

def thread(port):
    s = socket.socket()
    s.bind(('0.0.0.0', port))
    s.listen(500)
    while True:
        cli, addr = s.accept()
        t = threading.Thread(target=handle_request, args=(cli, time.sleep))
        t.daemon = True
        t.start()

结果:

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        
Server Hostname:        localhost
Server Port:            1115

Document Path:          /
Document Length:        10 bytes

Concurrency Level:      200
Time taken for tests:   0.229 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      5600 bytes
HTML transferred:       2000 bytes
Requests per second:    874.02 [#/sec] (mean)
Time per request:       228.827 [ms] (mean)
Time per request:       1.144 [ms] (mean, across all concurrent requests)
Transfer rate:          23.90 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    5   2.9      5      11
Processing:   101  107   3.8    107     116
Waiting:      101  107   3.9    106     115
Total:        105  112   1.5    112     116

Percentage of the requests served within a certain time (ms)
  50%    112
  66%    113
  75%    113
  80%    114
  90%    114
  95%    115
  98%    115
  99%    116
 100%    116 (longest request)

运行ab -r -n 200 -c 200,总共花时是0.229秒,现在我们用gevent做类线程的模拟操作:

import gevent
def greenlet(port):
    from gevent import socket
    s = socket.socket()
    s.bind(('0.0.0.0', port))
    s.listen(500)
    while True:
        cli, addr = s.accept()
        gevent.spawn(handle_request, cli, gevent.sleep)    

结果:

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        
Server Hostname:        localhost
Server Port:            1115

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      200
Time taken for tests:   0.012 seconds
Complete requests:      200
Failed requests:        597
   (Connect: 0, Receive: 398, Length: 0, Exceptions: 199)
Write errors:           0
Total transferred:      0 bytes
HTML transferred:       0 bytes
Requests per second:    16837.85 [#/sec] (mean)
Time per request:       11.878 [ms] (mean)
Time per request:       0.059 [ms] (mean, across all concurrent requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    2   2.2      4       5
Waiting:        0    0   0.0      0       0
Total:          0    2   2.2      4       5

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      4
  80%      4
  90%      5
  95%      5
  98%      5
  99%      5
 100%      5 (longest request)

我们看到总共花时不到0.012秒。

为什么不要一直使用gevent/greenlets呢?

为什么不要一直在gevent中greenlet?主要Greenlets使用协助式多任务,而线程使用抢占式多任务,意味着一个greenlet永远不会停止执行来让给另外的greenlet执行,除非它使用确切的'yielding'函数(像:gevent.socket.socket.recv或gevent.sleep),而线程完全是基于操作系统决定线程之间的切换的。

如果你使用python一段时间了,你应该听说过关于全局解释锁(GIL),它只允许在同一时刻单个线程执行python字节码。所以尽管在python中有线程和并发,但是线程所提供的好处不及C或者Java。

Gevent中还有些啥

希望在学习gevent时我能给你一些兴趣,gevent中还包括:

  • 提供monkey_patch标准库,所以你可以使用socket.socket而不需要gevent.socket 
  • 用自己的handlers处理基于socket连接的server。 
  • 在greenlet中更细粒度的控制spawn. 
  • greenlet pools 
  • greenlet-local对象 
  • 两个基于greentlet的WSGI服务器 

原文链接:Gevent简介,转载请注明来自foofish的博客

gevent 小结

最近用了 gevent,做个小结,理理对 gevent 的认识。 什么是 gevent? 简介 (摘自 官网) gevent is a coroutine-based...
  • LaoLiulaoliu
  • LaoLiulaoliu
  • 2015年01月04日 22:44
  • 2088

python Gevent – 高性能的Python并发框架

在python里,按照官方解释greenlet是轻量级的并行编程,而gevent呢,就是利用greenlet实现的基于协程的python的网络library,好了,关系理清了。。。 协程,gevent...
  • freeking101
  • freeking101
  • 2016年11月09日 11:10
  • 7255

python Gevent – 高性能的Python并发框架

话说gevent也没个logo啥的,于是就摆了这张图= =|||,首先这是一种叫做greenlet的鸟,而在python里,按照官方解释greenlet是轻量级的并行编程,而gevent呢,就是利用g...
  • tianmo2010
  • tianmo2010
  • 2012年08月21日 17:46
  • 27377

[gevent源码分析] 深度分析gevent运行流程

一直不太懂gevent运行流程,最近看源码略有所得,不敢独享,分享之。
  • yueguanghaidao
  • yueguanghaidao
  • 2014年04月25日 00:13
  • 23281

Gevent简介

介绍 gevent 是一个python网络框架,对应Java的netty框架,使用greenlet提供异步API,基于libevent ,它为各种并发和网络相关的任务提供了整洁的API. ...
  • permike
  • permike
  • 2016年08月29日 16:18
  • 730

gevent和pip的安装包

  • 2015年08月17日 15:18
  • 1.33MB
  • 下载

gevent程序员指南

gevent程序员指南 由Gevent社区编写 gevent是一个基于libev的并发库。它为各种并发和网络相关的任务提供了整洁的API。 介绍 本指南假定读者有中级P...
  • mbugatti
  • mbugatti
  • 2017年01月10日 10:59
  • 656

【Python2.7 gevent 库安装步骤】

gevent 安装之前要安装libevent    1.下载安装包 新版本是libevent-2.1.8-stable。(如果你的系统已经安装了libevent,可以不用安装) 官网:ht...
  • welcome00
  • welcome00
  • 2017年08月14日 13:44
  • 572

centos6.4 安装gevent

rpm 安装libevent-devel 出现依赖死循环
  • ming235cn
  • ming235cn
  • 2016年05月26日 16:24
  • 525

协程-gevent(python版)

gevent greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent 其原理是当一个g...
  • sinat_35360663
  • sinat_35360663
  • 2017年10月27日 09:35
  • 272
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Gevent简介
举报原因:
原因补充:

(最多只允许输入30个字)