Gunicorn (独角兽)是一个高效的Python WSGI Server,通常用它来运行 wsgi application(由我们自己编写遵循WSGI application的编写规范) 或者 wsgi framework(如Django,Paster),地位相当于Java中的Tomcat。
安装Gunicorn
方式一:最简单的使用 easy_install 安装或者更新
1 sudo easy_install -U gunicorn
方式二:下载源码安装
1 git clone git://github.com/benoitc/gunicorn.git 2 cd gunicorn 3 sudo python setup.py install
如果想让Gunicorn支持异步 workers 的话需要安装一下三个python包
1 easy_install -U greenlet 2 easy_install -U eventlet 3 easy_install -U gevent
说明:如果安装 greenlet 失败的话,你需要安装 Python headers
1 sudo apt-get install python-dev
gunicorn还需要库函数 libevent(1.4.x or 2.0.4)
运行Gunicorn
成功安装 gunicorn 之后有以下三个指令你可以直接使用,用来启动 gunicorn 运行 wsgi application或者 wsgi frameworks
1 gunicorn 2 gunicorn_django 3 gunicorn_paster
gunicorn
Gunicorn server的最基本的命令,直接用来运行最基本的 wsgi application 。
用法:
1 gunicorn [OPTIONS] APP_MODULE
OPTIONS 可选参数 运行gunicorn的配置选项,后面会讲到。
APP_MODULE 指定 wsgi application文件,书写格式 $(MODULE_NAME):$(VARIABLE_NAME)。其中 module_name用来制定将要运行的 wsgi application文件,可是一个完整的点缀名。比如当前目录 myapp 目录下有个 Python 包 gunicorn_app, gunicorn_app包下有一个wsgi application文件 test.py 则 module_name可以直接写成 gunicorn_app.test。viriable_name表示在 module_name 文件中要调用的对象(是一个WSGI callable, 可以是一个函数,类详情参看WSGI规格说明书)名。
按照上面的例子,当前目录为 /home/user/myapp, myapp中有一个包 gunicorn_app,test.py代码如下:
1 def app(environ, start_response): 2 """Simplest possible application object""" 3 data = 'Hello, World! ' 4 status = '200 OK' 5 response_headers = [ 6 ('Content-type','text/plain'), 7 ('Content-Length', str(len(data))) 8 ] 9 start_response(status, response_headers) 10 return iter([data])
我们将要运行 test.py文件中的 app(当然名字由你决定,可以是myapp,demo等等)
1 gunicorn gunicorn_app.test:app
命令中 module_name 为 gunicorn_app.test ;viriable_name为 app。当然如果我们这样直接运行Gunicorn的话,Gunicorn的所有配置都是默认值,后面会讲到如何配置Gunicorn。
gunicorn_django
guniorn_django命令是用来将 Django app部署到 Gunicorn Server上的。
其实也非常简单,原理和 gunicorn一样,只是gunicorn_django做了特殊处理,使得更加适合Django
基本用法
1 gunicorn_django [OPTIONS] [SETTINGS_PATH]
OPTIONS 前面已经说过了。
SETTINGS_PATH django app中 settings.py文件所在的目录,不写的话默认在当前目录下查找。比如:
1 gunicorn_django
这种用法适用以 Django 1.4 以前。
对于Django 1.4的版本以后推荐使用 gunicorn 命令(强烈推荐)
1 django_admin.py startproject mysite 2 cd mysite 3 gunicorn mysite.wsgi:application
还有一种方法是使用 Gunicorn内嵌的Djangohttps://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/gunicorn/不推荐。
至于 gunicorn_paster 有兴趣的可以研究 Gunicorn或者Paster官方文档。
Gunicorn配置
Gunicorn从三个不同的地方读取配置信息。
第一个地方:从framework定义的配置信息中读取,目前只对 Paster 框架有效。
第二个地方:在命令行中定义,命令行中定义的配置信息将会覆盖掉框架中定义的相同的参数名的值。
最后:将所有的参数信息,放到一个文件中,只要是在命令行中可以定义的参数中,在配置文件中都可以定义。(是一个Python源文件,所以你就像在写Python代码一样)
第一个地方不不介绍了,不实用。重点介绍第二种和第三种,其实这两种方式都是相同的。
显示说有配置选项:
1 gunicorn -h
使用命令行配置:
在上面的 myapp 例子的基础上
1 gunicorn --workers=4 --bind=127.0.0.1:8000 myapp.test:app
上面的命令 启动 4个 workers ,绑定到 127.0.0.1:8000
使用配置文件
配置文件 config.py 源码
1 import multiprocessing 2 3 bind = "127.0.0.1:8001" 4 workers = multiprocessing.cpu_count() * 2 + 1
使用配置文件启动Gunicorn
1 gunicorn --config=config.py myapp.test:app
和上面用命令行配置的效果完全一样。
当然两者还可以结合起来用:
1 gunicorn --config=gunicorn_conf.py --worker-class=eventlet myapp.test:app
worker-class默认是sync(同步),我们配置成了 eventlet(并发的)
Gunicorn的架构
服务模型(Server Model)
Gunicorn是基于 pre-fork 模型的。也就意味着有一个中心管理进程( master process )用来管理 worker 进程集合。Master从不知道任何关于客户端的信息。所有的请求和响应处理都是由 worker 进程来处理的。
Master(管理者)
主程序是一个简单的循环,监听各种信号以及相应的响应进程。master管理着正在运行的worker集合,通过监听各种信号比如TTIN, TTOU, and CHLD. TTIN and TTOU响应的增加和减少worker的数目。CHLD信号表明一个子进程已经结束了,在这种情况下master会自动的重启失败的worker。
Worker类型:
Sync Workers
The most basic and the default worker type is a synchronous worker class that handles a single request at a time. This model is the simplest to reason about as any errors will affect at most a single request. Though as we describe below only processing a single request at a time requires some assumptions about how applications are programmed.
Async Workers
The asynchronous workers available are based on Greenlets (via Eventlet and Gevent). Greenlets are an implementation of cooperative multi-threading for Python. In general, an application should be able to make use of these worker classes with no changes.
Tornado Workers
There’s also a Tornado worker class. It can be used to write applications using the Tornado framework. Although the Tornado workers are capable of serving a WSGI application, this is not a recommended configuration.
Choosing a Worker Type
The default synchronous workers assume that your application is resource bound in terms of CPU and network bandwidth. Generally this means that your application shouldn’t do anything that takes an undefined amount of time. For instance, a request to the internet meets this criteria. At some point the external network will fail in such a way that clients will pile up on your servers.
This resource bound assumption is why we require a buffering proxy in front of a default configuration Gunicorn. If you exposed synchronous workers to the internet, a DOS attack would be trivial by creating a load that trickles data to the servers. For the curious, Slowloris is an example of this type of load.
Some examples of behavior requiring asynchronous workers:
- Applications making long blocking calls (Ie, external web services)
- Serving requests directly to the internet
- Streaming requests and responses
- Long polling
- Web sockets
- Comet
How Many Workers?
DO NOT scale the number of workers to the number of clients you expect to have. Gunicorn should only need 4-12 worker processes to handle hundreds or thousands of requests per second.
Gunicorn relies on the operating system to provide all of the load balancing when handling requests. Generally we recommend (2 x $num_cores) + 1 as the number of workers to start off with. While not overly scientific, the formula is based on the assumption that for a given core, one worker will be reading or writing from the socket while the other worker is processing a request.
Obviously, your particular hardware and application are going to affect the optimal number of workers. Our recommendation is to start with the above guess and tune using TTIN and TTOU signals while the application is under load.
Always remember, there is such a thing as too many workers. After a point your worker processes will start thrashing system resources decreasing the throughput of the entire system。