首頁  >  文章  >  後端開發  >  python部署web開發的方法介紹

python部署web開發的方法介紹

Y2J
Y2J原創
2017-05-13 14:03:291487瀏覽

本篇文章主要介紹了Python部署web開發程式的幾種方法,具有很好的參考價值。下面跟著小編一起來看下吧

1、fastcgi ,透過flup模組來支持,在nginx裡對應的設定指令是fastcgi_pass

2、http,nginx使用proxy_pass轉送,這個要求後端appplication必須內建能處理高並發的http server,在python的web框架當中,只能選擇tornado.

#3、uwsgi,包括4部分組成:

  • uwsgi協定

  • web server內建支援協定模組

  • application伺服器協定支援模組

  • 程式控製程式

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 ),根紅苗正,而且部署比較簡單,gunicorn.org/ 上有詳細教學

9、mod_wsgi,apache的一個module,也是支援WSGI協定,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

参考: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协议在代码部署中的的优劣对比

  • fastcgi虽然是二进制协议,相对于http协议,并不节省资源。二进制协议,只能节省数字的表达,比如 1234567,用字符串表示需要7个Byte,用数字就是4个Byte,而字符串到哪里都一样

  • fastcgi在传输数据的时候,为了兼容cgi协议,还要带上一堆cgi的环境变量,所以和http协议相比,用fastcgi传输数据并不省,反而多一些

  • fastcgi 唯一的优点是,它是长连接的,用户并发1000个request,fastcgi可能就用10个 链接转发给后端的appplication,如果用http协议,那来多少给多少,会向后端appplication 发起1000个请求

  • http代理转发方式,在面对超高并发的情况下会出问题,因为,tcp协议栈当中,port是int16整型 你本地新建一个connect,需要消耗一个端口,最多能到65536。外部并发几十万个请求,port池耗干,你的服务器只能拒绝响应了

CGI, FCGI, SCGI, WSGI 区别

WIKI Links:

CGI - en.wikipedia.org/wiki/Common_Gateway_Interface
FCGI - en.wikipedia.org/wiki/Fcgi
SCGI - en.wikipedia.org/wiki/SCGI
WSGI - en.wikipedia.org/wiki/Wsgi 

Other reference:

helpful.knobs-dials.com/index.php/CGI%2C_FastCGI%2C_SCGI%2C_WSGI%2C_servlets_and_such#FastCGI_and_SCGI

CGI = Common Gateway Interface

顾名思义,它是一种接口规范。该规范详细定义了Web服务器中运行的服务器代理程序,怎样获取及返回网页生成过程中,服务器环境上下文和HTTP协议中的参数名称,如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE等等。绝大部分的Web服务器程序,是以脚本的形式代理接受并处理HTTP请求,返回HTTP页面或响应。这些脚本程序,就是大家所熟知的PHP、ASPJSP等等。

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 ,等等.

以上是python部署web開發的方法介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn