而这个过程中,一直可以拿来就用的三方库就是 gevent
在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
在任何时刻,只有一个协程在运行。
换句话说,协程并不会切换线程或进程(所以性能会比多线程高很多),而是在 IO 阻塞时,可以切换到其他的 Greenlet,等到适当时机再切换回来,这样减少阻塞浪费的时间,使其看起来像是在并发。所以协程可以解决 IO 密集的性能问题,而 CPU 密集则无能为力。
异步执行
使用 gunicorn 启动你的项目
1 2
|
$ pip install gunicorn $ pip install flask
|
1 2
|
$ touch gevent_without_code.py $ vim gevent_without_code.py
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
import time import socket from flask import Flask app = Flask(__name__)
print(socket.socket)
@app.route('/for') def get(): time.sleep(4) return "for"
@app.route('/bar') def get2(): return "bar"
|
不使用 gevent 启动
1 2 3 4 5 6 7 8
|
$ gunicorn gevent_without_code:app
[2019-03-27 23:06:53 +0800] [53872] [INFO] Starting gunicorn 19.7.1 [2019-03-27 23:06:53 +0800] [53872] [INFO] Listening at: http://127.0.0.1:8000 (53872) [2019-03-27 23:06:53 +0800] [53872] [INFO] Using worker: sync [2019-03-27 23:06:53 +0800] [53932] [INFO] Booting worker with pid: 53932 <class 'socket.socket'> [2019-03-27 23:06:56 +0800] [53872] [INFO] Handling signal: winch
|
gunicorn 默认启动一个 8000 端口的 web 程序,我们有两个接口
/for
强制睡眠 4 秒钟,
/bar
直接返回结果
这时候我们先访问
/for
在访问
/bar
会发生阻塞
/bar
需要等待
/for
返回结果后才能执行,这显然不是一个健康的程序。我们试试使用 gevent。
<ctrl> + c
停掉程序,重新启动
1 2 3 4 5 6
|
$ gunicorn gevent_without_code:app -k gevent [2019-03-27 23:16:41 +0800] [63766] [INFO] Starting gunicorn 19.7.1 [2019-03-27 23:16:41 +0800] [63766] [INFO] Listening at: http://127.0.0.1:8000 (63766) [2019-03-27 23:16:41 +0800] [63766] [INFO] Using worker: gevent [2019-03-27 23:16:41 +0800] [63826] [INFO] Booting worker with pid: 63826 <class 'gevent._socket3.socket'>
|
再次访问两个接口,效果非常明显
当
/for
阻塞时,gevent 直接跳过执行
/bar
,等阻塞过后,在继续执行
/for
。
这里我们一句 gevent 代码都没写,那它是什么实现的呢?
如果你留意刚才的启动日志,会发现我们代码有句
print(socket.socket)
,在使用 gevent 前后是有不同的。
1 2 3 4 5 6 7
|
... <class 'socket.socket'> ...
... <class 'gevent._socket3.socket'> ...
|
就像我们上面讲到的那样,gevent 在这里隐形的调用了
gevent.monkey.patch_all()
方法,使得相关的程序都自动变成了协程可调用的状态。
不管你代码写的怎么样,用 gevent 来启动你的项目吧,一定会让你觉得物有所值。
本文 demo 源码
gevent 源码
gevent 程序员指南
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent:
meta: false
pages: false
posts:
title: true
date: true
path: true
text: false
raw: false
content: false
slug: false
updated: false
comments: false
link: false
permalink: false
excerpt: false
categories: false
tags: true