当前位置:首页 > 服务端 > Python生产环境部署(fastcgi,uwsgi)

Python生产环境部署(fastcgi,uwsgi)

2022年11月06日 10:30:02服务端8

Python部署web开发程序的几种方法

  • fastcgi ,通过flup模块来支持,在nginx里对应的配置指令是 fastcgi_pass

  • http,nginx使用proxy_pass转发,这个要求后端appplication必须内置一个能处理高并发的http server,在python的web框架当中,只能选择tornado.

  • 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)等等

  • mod_python,这是apache内置的模块,很严重的依赖于mod_python编译使用的python版本,和apache配套使用,不推荐

  • cgi,这个太old,不推荐,而且nginx不支持cgi方式,只能用lighttpd或者apache

  • spawn-fcgi,这个是fastcgi多进程管理程序,lighttpd安装包附带的,和 flup效果一样,区别是flup是 python代码级引入,spawn-fcgi是外部程序。spawn-fcgi用途很广,可以支持任意语言开发的代码,php,python,perl,只要你代码实现了fastcgi接口,它都可以帮你管理你的进程

  • scgi,全名是Simple Common Gateway Interface,也是cgi的替代版本,scgi协议很简单,我觉得和fastcgi差不多,只是没有怎么推广开来,nginx对应的配置指令是scgi_pass,你想用就用,flup也支持。

  • Gunicorn,和uwsgi类似的工具,从rails的部署工具(Unicorn)移植过来的。但是它使用的协议是 WSGI,全称是Python Web Server Gateway Interface ,这是python2.5时定义的官方标准(PEP 333 ),根红苗正,而且部署比较简单,http://gunicorn.org/ 上有详细教程

  • 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

配置示例

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
$ 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
$
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

配置参数详解:

常用选项:

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

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
$ 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
$ 
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

 

配置application

flask 示例

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
...
app = Flask('pan')
...

if __name__ == '__main__':
    # app.run(host='0.0.0.0', port=5000)
    app.run()

# 注意:变量app对应uwsgi配置文件uwsgi.ini中 callable = app 
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

 

启动uwsgi

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
$ 
$ uwsgi --ini /usr/local/etc/uwsgi.ini
[uWSGI] getting INI configuration from /usr/local/etc/uwsgi.ini
$ 
$ ps -ef|grep uwsgi
  501 11428     1   0 11:40下午 ??         0:01.23 uwsgi --ini /usr/local/etc/uwsgi.ini
  501 11432 11428   0 11:40下午 ??         0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
  501 11433 11428   0 11:40下午 ??         0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
  501 11434 11428   0 11:40下午 ??         0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
  501 11435 11428   0 11:40下午 ??         0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini
  501 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)
$
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

 

FCGI

参考:http://webpy.org/cookbook/fastcgi-nginx

配置Nginx

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
$ 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/;
    }

}

$
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

 

配置application

简单示例

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
from flup.server.fcgi import WSGIServer
from pan import app

WSGIServer(
    app,
    bindAddress=(host, port),
maxThreads=threads ).run()
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

生产环境示例

Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记
#!/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)
Python生产环境部署(fastcgi,uwsgi) _ JavaClub全栈架构师技术笔记

 

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

 http://www.cnblogs.com/suoning/p/6786621.html

 

作者:沧海一滴
来源链接:https://www.cnblogs.com/softidea/p/6855214.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/68145.html

标签: Python
分享给朋友:

“Python生产环境部署(fastcgi,uwsgi)” 的相关文章

[Python] 字典操作近两万字大总结(超详细教程)

[Python] 字典操作近两万字大总结(超详细教程)

🔥 信仰:一个人走得远了,就会忘记自己为了什么而出发,希望你可以不忘初心,不要随波逐流,一直走下去 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 🦄 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏:Python学习 🌠 首发时间:2022年5月...

【python】函数用法详解(一)

【python】函数用法详解(一)

✅作者简介:大家好我是姐姐划船吗?让我们一起共同进步吧!🏆 📃个人主页:姐姐划船吗? 🔥系列专栏:学会python,逆天改命 💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞 💬格言:静坐要辨己过,闲谈莫论人非🔥 学习目标:   &nbs...

Python "爬虫"出发前的装备之一正则表达式

1. 正则表达式 正则表达式是一种模板表达式语言 通过定义规则去匹配、查找、替换、分割一个长字符串中特定的子字符信息。 如在一篇文章中查找出所有合法的电子邮箱地址,则可以先用正则表达式定义一个电子邮箱规则,然后再使用这个规则在整个字符串中查找。 爬虫程序一般都会...

Python 散列表查询

Python 散列表查询

1. 前言 哈希表或称为散列表,是一种常见的、使用频率非常高的数据存储方案。 哈希表属于抽象数据结构,需要开发者按哈希表数据结构的存储要求进行 API 定制,对于大部分高级语言而言,都会提供已经实现好的、可直接使用的 API,如 JAVA 中有 MAP 集合、C++ 中的...

Python  turtle  模块可以编写游戏,是真的吗?

Python turtle 模块可以编写游戏,是真的吗?

1. 前言 turtle (小海龟) 是 Python 内置的一个绘图模块,其实它不仅可以用来绘图,还可以制作简单的小游戏,甚至可以当成简易的 GUI 模块,编写简单的 GUI 程序。 本文使用 turtle 模块编写一个简单的小游戏,通过此程序的编写过程聊一聊对 turt...

python中循环的技巧

循环的技巧 在字典中循环时,用 items() 方法可同时取出键和对应的值: >>> >>> knights = { 'gallahad': 'the pure', 'robin': 'th...

Python快速学习09: 函数的参数

Python快速学习09: 函数的参数

前言   系列文章:[传送门]   继续干起来!!   正文     我们已经接触过函数,函数是可以被引用的(访问或者以其他变量作为其别名),也作为参数传入函数,以及作为列表和字典等等容器...

Python快速学习05:面向对象

Python快速学习05:面向对象

        系列文章:[传送门]  Python对象是Python语言的核心部分。Python使用类(class)和对象(object),进行面向对象(object-oriented programming...

python常用时间处理方法

常用时间处理方法 今天 today = datetime.date.today() 昨天 yesterday = today - datetime.timedelta(days=1) 上个月 last_month = today.month - 1...

Python执行.sh脚本cataline环境变量配置

Python执行.sh脚本cataline环境变量配置

注:参考文档:https://blog.csdn.net/weixin_38322156/article/details/72852607;https://blog.csdn.net/johnnysun2015/article/details/78414684 一:问题,最近在用...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。