Python的Gevent框架的多进程模式

Gevent框架性能很高,但一直以来我都纠结在python的GIL模型导致的线程不能抢占多核资源上面。

而启动多个python进程的这种利用多核的模式又需要增加前端负载均衡,比如lvs那些,有些麻烦。

multiprocessing模块和os.fork又会使得两个进程重复在事件核心注册accept事件,导致文件句柄重复的异常。

至于一个进程监听,多个进程处理的模式,监听的那个进程资源又不好分配——是独立分配一个核心还是不单独分配呢?如果单独分配,连接量小的时候就浪费了一个核心,如果不分配,连接量大的时候cpu又会频繁切换进程。

昨日才发现原来gevent是可以很轻松地将它的网络模型分布到多个进程并行处理的。

秘诀就在gevent.fork()。

以前想当然地认为gevent.fork只是greenlet.spawn的一个包装,原来不是这样。gevent.fork能替代os.fork,不仅会启动一个新的进程,而且能将它们底层的事件处理沟通起来,进行并行处理。

1import gevent 2from gevent.server import StreamServer 3 4def eat_cpu(): 5 for i in xrange(10000): pass 6 7def cb(socket, address): 8 eat_cpu() 9 socket.recv(1024) 10 socket.sendall('HTTP/1.1 200 OK\n\nHello World!!') 11 socket.close() 12 13server = StreamServer(('',80), cb, backlog=100000) 14server.pre_start() 15 16gevent.fork() 17 18server.start_accepting() 19server._stopped_event.wait()

 打上monkey.patch_os后,os.fork就可以被gevent.fork替代了,这样同时multiprocessing模块也可以像往常一样使用,并达到并行处理的效果了。

1from gevent import monkey; monkey.patch_os() 2from gevent.server import StreamServer 3from multiprocessing import Process 4 5def eat_cpu(): 6 for i in xrange(10000): pass 7 8def cb(socket, address): 9 eat_cpu() 10 socket.recv(1024) 11 socket.sendall('HTTP/1.1 200 OK\n\nHello World!!') 12 socket.close() 13 14server = StreamServer(('',80), cb, backlog=100000) 15server.pre_start() 16 17def serve_forever(): 18 server.start_accepting() 19 server._stopped_event.wait() 20 21process_count = 4 22 23for i in range(process_count - 1): 24 Process(target=serve_forever, args=tuple()).start() 25 26serve_forever()

简单地作了一下测试

测试环境:

CPU AMD Athlon(tm) II X4 640 3.01GHz

内存 2G DDR2

操作系统 CentOS 6.0 (虚拟机内)

测试命令 ab -n 10000 -c 100 http://127.0.0.1/

测试结果:

1个进程    1534.13 个请求每秒    是一个进程的1倍

2个进程    3056.48 个请求每秒    是一个进程的1.99倍

3个进程    4460.04 个请求每秒    是一个进程的2.90倍

由于ab需要单独用一个核心,所以就只测试3个进程的结果。

可以看到每秒处理的请求数随着进程数的提升也会有几乎成倍的提升。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid