这里有新鲜出炉的 Python 多线程编程,程序狗速度看过来!
Python 是一种面向对象、解释型计算机程序设计语言,由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。Python 语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。
本篇文章主要介绍了 Python 部署 web 开发程序的几种方法,具有很好的参考价值。下面跟着小编一起来看下吧
1、fastcgi ,通过 flup 模块来支持,在 nginx 里对应的配置指令是 fastcgi_pass
2、http,nginx 使用 proxy_pass 转发, 这个要求后端 appplication 必须内置一个能处理高并发的 http server,在 python 的 web 框架当中,只能选择 tornado.
3、uwsgi, 包括 4 部分组成:
nginx 从 0.8.4 开始内置支持 uwsgi 协议,uwsgi 协议非常简单,一个 4 个字节 header + 一个 body,body 可以是很多协议的包,比如说 http,cgi 等(通过 header 里面字段标示)。
uwsgi 的特点在于自带的进程控制程序. 它是用 c 语言编写,使用 natvie 函数,其实和 spawn-fcgi/php-fpm 类似。所以 uwsgi 可以支持多种应用框架,包括 (python,lua,ruby,erlang,go) 等等
4、mod_python, 这是 apache 内置的模块,很严重的依赖于 mod_python 编译使用的 python 版本,和 apache 配套使用,不推荐
5、cgi,这个太 old,不推荐,而且 nginx 不支持 cgi 方式,只能用 lighttpd 或者 apache
6、spawn-fcgi,这个是 fastcgi 多进程管理程序,lighttpd 安装包附带的,和 flup 效果一样,区别是 flup 是 python 代码级引入,spawn-fcgi 是外部程序。spawn-fcgi 用途很广,可以支持任意语言开发的代码,php,python,perl, 只要你代码实现了 fastcgi 接口,它都可以帮你管理你的进程
7、scgi, 全名是 Simple Common Gateway Interface,也是 cgi 的替代版本,scgi 协议很简单, 我觉得和 fastcgi 差不多,只是没有怎么推广开来,nginx 对应的配置指令是 scgi_pass,你想用就用,flup 也支持。
8、Gunicorn, 和 uwsgi 类似的工具,从 rails 的部署工具 (Unicorn) 移植过来的。但是它使用的协议是 WSGI,全称是 Python Web Server Gateway Interface ,这是 python2.5 时定义的官方标准(PEP 333),根红苗正,而且部署比较简单,http://gunicorn.org/ 上有详细教程
9、mod_wsgi,apache 的一个 module,也是支持 WSGI 协议, https://code.google.com/p/modwsgi/
uwsgi
安装 uwsgi
- pip install uwsgi
配置 uwsgi
uwsgi 有多种配置可用:
- 1,ini
- 2,xml
- 3,json
- 4,yaml
配置示例
- $ cat etc/uwsgi.ini
- [uwsgi]
- socket = 127.0.0.1:9005
- chdir = /Users/suoning/python_project/trunk/
- wsgi-file = main.py
- processes = 4
- stats = 127.0.0.1:9000
- daemonize = /tmp/uwsgiServer.log
- pidfile = /tmp/uwsgi.pid
- vacuum = true
- log-maxsize = 50000000
- disable-logging = true
- callable = app
- $
配置参数详解:
常用选项:
socket : 地址和端口号,例如:socket = 127.0.0.1:50000
processes : 开启的进程数量
workers : 开启的进程数量,等同于 processes(官网的说法是 spawn the specified number of workers / processes)
chdir : 指定运行目录(chdir to specified directory before apps loading)
wsgi-file :载入 wsgi-file(load .wsgi file)
stats : 在指定的地址上,开启状态服务(enable the stats server on the specified address)
threads : 运行线程。由于 GIL 的存在,我觉得这个真心没啥用。(run each worker in prethreaded mode with the specified number of threads)
master :允许主进程存在(enable master process)
daemonize : 使进程在后台运行,并将日志打到指定的日志文件或者 udp 服务器(daemonize uWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。
log-maxsize :以固定的文件大小(单位 KB),切割日志文件。 例如:log-maxsize = 50000000 就是 50M 一个日志文件。
pidfile : 指定 pid 文件的位置,记录主进程的 pid 号。
vacuum :当服务器退出的时候自动清理环境,删除 unix socket 文件和 pid 文件(try to remove all of the generated file/sockets)
disable-logging : 不记录请求信息的日志。只记录错误以及 uWSGI 内部消息到日志中。如果不开启这项,那么你的日志中会大量出现这种记录:
[pid: 347|app: 0|req: 106/367] 117.116.122.172 () {52 vars in 961 bytes} [Thu Jul 7 19:20:56 2016] POST /post => generated 65 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 88 bytes (1 switches on core 0)
配置 nginx
- $ cat etc/nginx/servers/tongbupan.conf
- server {
- listen 80;
- server_name localhost;
- location / {
- include uwsgi_params;
- uwsgi_pass 127.0.0.1:9005;
- }
- location /webstatic/ {
- expires 7d;
- add_header Cache-Control public;
- alias /Users/suoning/probject/python_project/webstatic/trunk/;
- }
- }
- $
- $ nginx -t
- nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
- nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
- $
- $ nginx -s reload
- $
配置 application
flask 示例
- ...
- app = Flask('pan')
- ...
- if __name__ == '__main__':
- # app.run(host='0.0.0.0', port=5000)
- app.run()
- # 注意:变量app对应uwsgi配置文件uwsgi.ini中 callable = app
启动 uwsgi
- $
- $ uwsgi --ini /usr/local/etc/uwsgi.ini
- [uWSGI] getting INI configuration from /usr/local/etc/uwsgi.ini
- $
- $ ps -ef|grep uwsgi
- 11428 1 0 11:40下午 ?? 0:01.23 uwsgi --ini /usr/local/etc/uwsgi.ini
- 11432 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
- 11433 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
- 11434 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
- 11435 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
- 11440 69240 0 11:40下午 ttys000 0:00.00 grep uwsgi
- $
- $ lsof -i tcp:9000
- COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- uwsgi 11428 suoning 28u IPv4 0x5583e11534d24e73 0t0 TCP localhost:cslistener (LISTEN)
- $
- $ lsof -i tcp:9005
- COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- uwsgi 11428 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN)
- uwsgi 11432 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN)
- uwsgi 11433 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN)
- uwsgi 11434 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN)
- uwsgi 11435 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN)
- $
FCGI
参考:http://webpy.org/cookbook/fastcgi-nginx
配置 Nginx
- $ cat etc/nginx/servers/pan.conf
- server {
- listen 80;
- server_name localhost;
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- location / {
- fastcgi_param REQUEST_METHOD $request_method;
- fastcgi_param QUERY_STRING $query_string;
- fastcgi_param CONTENT_TYPE $content_type;
- fastcgi_param CONTENT_LENGTH $content_length;
- fastcgi_param GATEWAY_INTERFACE CGI/1.1;
- fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
- fastcgi_param REMOTE_ADDR $remote_addr;
- fastcgi_param REMOTE_PORT $remote_port;
- fastcgi_param SERVER_ADDR $server_addr;
- fastcgi_param SERVER_PORT $server_port;
- fastcgi_param SERVER_NAME $server_name;
- fastcgi_param SERVER_PROTOCOL $server_protocol;
- fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
- fastcgi_param PATH_INFO $fastcgi_script_name;
- fastcgi_pass 127.0.0.1:9005;
- }
- location /webstatic/ {
- expires 7d;
- add_header Cache-Control public;
- alias /Users/suoning/probject/python_project/webstatic/trunk/;
- }
- }
- $
配置 application
简单示例
- from flup.server.fcgi import WSGIServer
- from pan import app
- WSGIServer(
- app,
- bindAddress=(host, port),
- maxThreads=threads
- ).run()
生产环境示例
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- __author__ = 'suoning'
- import sys
- import argparse
- from flup.server.fcgi import WSGIServer
- from lib.daemon import Daemon
- from pan import app
- APP_NAME = 'pan_platform'
- APP_INST_NAME = '20170501'
- parser = argparse.ArgumentParser(description=u'Run an pan FastCGI server')
- parser.add_argument('command', type=str,
- help=u'command [start|stop|restart]',
- choices=['start', 'stop', 'restart'])
- parser.add_argument('-p', '--port', type=int,
- help=u'port of this server', required=True)
- parser.add_argument('-t', '--threads', type=int, default=50,
- help=u'max number of threads')
- parser.add_argument('-host', '--host', default='0.0.0.0',
- help=u'Listen to the main clause')
- class panPlatformDaemon(Daemon):
- def run(self):
- # 运行服务
- try:
- WSGIServer(
- app,
- bindAddress=(args.host, args.port),
- maxThreads=args.threads,
- umask=0111
- ).run()
- except:
- sys.stderr.write('oops')
- def gen_pidfile(port):
- return '/var/run/%s_%s_%d.pid' % (APP_NAME, APP_INST_NAME, port)
- if __name__ == '__main__':
- args = parser.parse_args()
- daemon = panPlatformDaemon(gen_pidfile(args.port))
- if 'start' == args.command:
- daemon.start()
- elif 'stop' == args.command:
- daemon.stop()
- elif 'restart' == args.command:
- daemon.restart()
- else:
- print "Unknown command"
- sys.exit(2)
- sys.exit(0)
fastcgi 协议和 http 协议在代码部署中的的优劣对比
CGI, FCGI, SCGI, WSGI 区别
WIKI Links:
CGI - http://en.wikipedia.org/wiki/Common_Gateway_Interface FCGI - http://en.wikipedia.org/wiki/Fcgi SCGI - http://en.wikipedia.org/wiki/SCGI WSGI - http://en.wikipedia.org/wiki/Wsgi
Other reference:
http://helpful.knobs-dials.com/index.php/CGI,_FastCGI,_SCGI,_WSGI,_servlets_and_such#FastCGI_and_SCGI
CGI = Common Gateway Interface
顾名思义,它是一种接口规范。该规范详细定义了 Web 服务器中运行的服务器代理程序,怎样获取及返回网页生成过程中,服务器环境上下文和 HTTP 协议中的参数名称,如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE 等等。绝大部分的 Web 服务器程序,是以脚本的形式代理接受并处理 HTTP 请求,返回 HTTP 页面或响应。这些脚本程序,就是大家所熟知的 PHP、ASP、JSP 等等。
FCGI = Fast CGI
它其实是 CGI 在具体实现中的的一个变种。其设计思路是,通过减少 CGI 代理程序和 Web 宿主服务程序的通信开销,从而达到提高 Web 服务性能的最终目的。由此可见,FCGI 在规范上跟 CGI 并没有不同,只是具体实现方式上有所改进:CGI 的做法是,对于每个 HTTP 请求,Web 宿主服务程序都建立新的进程以调用服务器脚本,相应该请求;FCGI 的做法是,建立一个独立的 FCGI 服务程序进程,和 Web 宿主服务程序进程通信,FCGI 服务进程被一旦启动后,自己分配资源、创建线程响应 HTTP 请求、并决定自身生命周期,从而大大降低了系统为了创建进程而做出的资源开销。现代流行的 Web 服务器程序,如 PHP、ASP.Net,基本都是 FCGI 的实现。
SCGI = Simple CGI
它是 FCGI 在精简数据协议和响应过程后的产物。其设计目的是为了适应越来越多基于 AJAX 或 REST 的 HTTP 请求,而做出更快更简洁的应答。并且 SCGI 约定,当服务器返回对一个 HTTP 协议请求响应后,立刻关闭该 HTTP 连接。所以不难看出,SCGI 更加适合于普遍意义上 SOA 所提倡的 "请求 - 忘记" 这种通信模式。
WSGI = Web Server Gateway Interface
此协议是 Python 语言的专利,它定义了一组在 Web 服务宿主程序和 HTTP 响应代理程序之间通信的普遍适用的接口。它的产生是因为 Python 程序员注意到,对于 Web 框架和 Web 宿主服务器程序间,有严重的耦合性,比如说,某些框架是针对 Apache 的 mod_python 设计的。于是,WSGI 就定义了一套非常低级别的接口。常见的 Python Web 框架都实现了这个协议:如 CherryPy, Django, web.py, web2py, TurboGears, Tornado, Pylons, BlueBream, Google App Engine[dubious – discuss], Trac, Flask, Pyramid, 等等.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持 PHPERZ!
来源: http://www.phperz.com/article/17/0529/334812.html