Python的Gevent框架的多进程模式

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

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

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

至于一个进程监听,多个进程处理的模式,监听的那个进程资源又很差分配——是独立分配一个核心仍是不单独分配呢?若是单独分配,链接量小的时候就浪费了一个核心,若是不分配,链接量大的时候cpu又会频繁切换进程。负载均衡

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

秘诀就在gevent.fork()。socket

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

import gevent
from gevent.server import StreamServer

def eat_cpu():
    for i in xrange(10000): pass

def cb(socket, address):
    eat_cpu()
    socket.recv(1024)
    socket.sendall('HTTP/1.1 200 OK\n\nHello World!!')
    socket.close()

server = StreamServer(('',80), cb, backlog=100000)
server.pre_start()

gevent.fork()

server.start_accepting()
server._stopped_event.wait()

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

from gevent import monkey; monkey.patch_os()
from gevent.server import StreamServer
from multiprocessing import Process

def eat_cpu(): 
    for i in xrange(10000): pass

def cb(socket, address):
    eat_cpu()
    socket.recv(1024)
    socket.sendall('HTTP/1.1 200 OK\n\nHello World!!')
    socket.close()

server = StreamServer(('',80), cb, backlog=100000)
server.pre_start()

def serve_forever():
    server.start_accepting()
    server._stopped_event.wait()

process_count = 4

for i in range(process_count - 1):
    Process(target=serve_forever, args=tuple()).start()

serve_forever()

简单地做了一下测试spa

测试环境:操作系统

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个进程的结果。

能够看到每秒处理的请求数随着进程数的提高也会有几乎成倍的提高。

相关文章
相关标签/搜索