使用uwsgi 部署python web服务

uwsgi, wsgi协议的一个很好的实现,源码在这里:https://github.com/unbit/uwsgi

c语言编写,有兴趣可以研究下。

DEMO

wsgi_server.py

def application(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return 'hello world'

应用:

使用uwsgi部署以上应用:

uwsgi --http 0.0.0.0:9090 -p 4 -l 100 -M -R 100000  -z30 -L --wsgi-file  wsgi_server.py --max-apps 65535 --stats 127.0.0.1:1717 --post-buffering 100M --cpu-affinity --buffer-size 65535 --daemonize /tmp/uwsgi --pidfile /tmp/uwsgi.pid  --memory-report --threads 4

然后浏览器访问: http://localhost:9090/ 即可。

优势:

提高并发访问支持(-p 进程数, --threads  线程数)

提高服务运行稳定性(--daemonize)

安装

pip install uwsgi
pip install uwsgitop

uwsgi--uwsgi服务器

uwsgitop--uwsgi服务器性能查看工具,用法:

配合以上例子

uwsgitop 127.0.0.1:1717

参数详细说明

官方文档:http://uwsgi-docs.readthedocs.io/en/latest/Options.html

不错的中文文档:http://www.cnblogs.com/zhouej/archive/2012/03/25/2379646.html

挑几个重点:

--wsgi-file , 指定wsgi入口文件

-p  , workers个数,也是进程数, 按照惯例可默认设为核数,但是不是最优配置需要通过 uwsgitop来查看(个人觉得uwsgitop没啥用)。

--threads , 线程数, 每个进程的线程数,进程的任务用线程的模式完成。由于用c编写,因此不用担心GIL的问题, 但linux上不存在线程,线程本质来讲是伪进程(且存在上下文切换成本),因此不建议使用。

(用了后,再用uwsgitop监控时,可通过键盘的“A”键查看线程的资源占用情况)

--listen (-l), 内核监听(listen)网络队列的长度,受文件操作系统最大的网络连接数(net.core.somaxconn) 的限制, 长度越大意味着在高并发的环境下,丢失请求越少。

--cpu-affinity, cpu友好,即进程在运行时不切换核(切换意味着时间成本)

--stats,  监控程序的url,只有设置了这个参数以后才能用 uwsgitop 1717来观看监控

--memory-report, 开启内存占用报告(uwsgitop中可以看到) 

--master(-M), 启动主进程,方便管理所有进程, 可以配合--pidfie 使用。方便停止(uwsgi --stop /tmp/uwsgi.pid)/重启uwsgi ( uwsgi --reload /tmp/uwsgi.pid)

--daemonize, 增加守护进程,使web服务更加稳定。参数为日志文件的路径。

--disable-loggin, 不记录请求信息的日志。只记录错误以及uWSGI内部消息到日志中。

其他略,可以自己逐一尝试。

用途

flask必需搭配使用咯。

django建议使用,默认支持,有默认的wsgi.py文件生成。

1. flask 

uwsgi -s /tmp/uwsgi.sock --manage-script-name --mount /=xxx_project:app --http 0.0.0.0:9091

xxx_project换为具体的项目文件顶层文件夹。

2. django

 django官方介绍

uwsgi --chdir=/path/to/project/site_app  --module=site_app.wsgi:application  --env DJANGO_SETTINGS_MODULE=site_app.settings

 uwsgi官方介绍:http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html#test-your-django-project。

uwsgi --http :8000 --module web_app.wsgi

相对来说后者简单粗暴。

进一步的并发提升

+nginx,

为啥呢?看这里:http://www.oschina.net/translate/serving-python-web-applications?lang=eng

即:

I was pretty proud when we got API response times down to 40ms on average. When I say API I’m only talking about the time it takes from it hitting the Python server, to the server returning it’s response to the proxy.
Unfortunately, it quickly became apparent that there were capacity issues when we started getting more traffic for larger spikes. We’d hit bumpy response times that were no longer consistent, but we still had about 30% memory and 60% cpu to spare on the web nodes.

即:实测发现,uwsgi似乎不能充分的利用cpu和内存来达到无上限的并发。有一定瓶颈,并且到达瓶颈后,cpu和内存还剩下很多!

那为了充分利用资源不妨多开几个uwsgi服务咯。

老外实测发现: 与其让一个uwsgi服务跑10个进程,不如开10个uwsgi服务,然后用nginx做负载均衡!

After quite a few tweaks, what we eventually settled on was managing a larger amount of uwsgi processes, and letting nginx load balance them (vs letting uwsgi itself load balance).

What this means, is that instead of doing uwsgi –processes=10, we ran 10 separate uwsgi processes.

The result was a beautiful, consistent 20ms average response time.

当然这个有待验证。

简单说,就是uwsgi本身的负载均衡没有nginx牛逼。所以阉割掉不用。

因此uwsgi退化成了wsgi服务器。

nginx 咋配置,略。

转载请注明来自:http://www.cnblogs.com/Tommy-Yu/p/5647730.html,谢谢!