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個進程的結果。
能夠看到每秒處理的請求數隨着進程數的提高也會有幾乎成倍的提高。