路漫漫其修远兮
吾将上下而求索

python学习:flask + gunicorn + supervisor + nginx

flask   python 的服务器框架
gunicorn   webservice,WSGI 的容器
supervisor   进程管理工具
nginx   一个高性能的 web 服务器


[root@master ~]#mkdir -p /data/blog
[root@master ~]#cd /data/blog
[root@master /data/blog]#python3 -m venv venv
[root@master /data/blog]#ls
venv
[root@master /data/blog]#source venv/bin/activate

(venv) [root@master /data/blog]#pip install flask gunicorn

(venv) [root@master /data/blog]#cat myapp.py 
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return 'hello world'
if __name__ == '__main__':
    app.debug = True
    app.run(host = '0.0.0.0', port = 8080)

#直接运行方式
(venv) [root@master /data/blog]#python myapp.py 

#多进程运行方式
#-w 表示开启了多少个 worker, -b 表示访问地址。myapp 就是 myapp.py 的文件名,mypp.py 相当于一个库文件被 gunicorn 调用。
app 则是 myapp.py 里创建的 app,这样 gunicorn 才可以定位 flask 应用。

(venv) [root@master /data/blog]#gunicorn -w 4 -b 0.0.0.0:8080 --chdir /data/blog myapp:app

#或者将参数写入配置文件
(venv) [root@master /data/blog]#cat gunicorn.py 
# gunicorn.py
import logging
import logging.handlers
from logging.handlers import WatchedFileHandler
import os
import multiprocessing
bind = '0.0.0.0:8080'      #绑定ip和端口号
backlog = 512                #监听队列
chdir = '/data/blog'  #gunicorn要切换到的目的工作目录
timeout = 30      #超时
#worker_class = 'gevent' #使用gevent模式,还可以使用sync 模式,默认的是sync模式

workers = 10    #进程数
#threads = 2 #指定每个进程开启的线程数
loglevel = 'info' #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'    #设置gunicorn访问日志格式,错误日志无法设置

"""
其每个选项的含义如下:
h          remote address
l          '-'
u          currently '-', may be user name in future releases
t          date of the request
r          status line (e.g. ``GET / HTTP/1.1``)
s          status
b          response length or '-'
f          referer
a          user agent
T          request time in seconds
D          request time in microseconds
L          request time in decimal seconds
p          process ID
"""
accesslog = "/data/blog/log/gunicorn_access.log"      #访问日志文件
errorlog = "/data/blog/log/gunicorn_error.log"        #错误日志文件

#创建日志目录并启动
(venv) [root@master /data/blog]#mkdir log
(venv) [root@master /data/blog]#/data/blog/venv/bin/gunicorn -c /data/blog/gunicorn.py myapp:app



#用supervisor来管理进程
#想结束 gunicorn 可以通过执行 pkill gunicorn,有时还要找到 pid 才能 kill 掉。这样的操作过于繁琐,所以我们使用另一个神器 supervisor, 用来专门管理系统的进程。
(venv) [root@master /data/blog]#yum install -y supervisor

(venv) [root@master /data/blog]#vim /etc/supervisord.conf
#最后面添加如下
[program:myapp]
directory=/data/blog
command=/data/blog/venv/bin/gunicorn -c /data/blog/gunicorn.py myapp:app    ; supervisor启动命令
process_name==%(program_name)s_%(process_num)02d
numprocs=1
startsecs=0                                                                             ; 启动时间
stopwaitsecs=0                                                                          ; 终止等待时间
autostart=true                                                                         ; 是否自动启动
autorestart=true                                                                       ; 是否自动重启
log_stdout=false ;输出到标准输出的都会记录到日志中
log_stderr=false
logfile=/data/blog/log/gunicorn.log                           ; log 日志


[root@master ~/blog]#service supervisord restart

到这里基础环境成功


将blog项目导入:tag为13b
(venv) [root@master /data/blog]#mv ../flasky-c4e26260acf55df55b7e5c2cb0b581f3db29f60d/* .                             */
(venv) [root@master /data/blog]#ls
app        gunicorn.py  log        migrations  __pycache__  requirements  venv
config.py  LICENSE      manage.py  myapp.py    README.md    tests

#安装依赖包
venv) [root@master /data/blog]#pip install -r requirements/dev.txt

#初始化数据库
venv) [root@master /data/blog]#python manage.py db upgrade

#修改配置文件
(venv) [root@master /data/blog]#vim config.py
class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_RECORD_QUERIES = True
    MAIL_SERVER = 'smtp.ym.163.com'
    MAIL_PORT = 25
    MAIL_USE_TLS = False
    MAIL_USERNAME = "a@b.com"
    MAIL_PASSWORD = "aaa"
    FLASKY_MAIL_SUBJECT_PREFIX = '[Andyblog]'
    FLASKY_MAIL_SENDER = "a@b.com"
    FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN')
    FLASKY_POSTS_PER_PAGE = 20
    FLASKY_FOLLOWERS_PER_PAGE = 50
    FLASKY_COMMENTS_PER_PAGE = 30
    FLASKY_SLOW_DB_QUERY_TIME=0.5

    @staticmethod
    def init_app(app):
        pass  


#修改myapp.py为项目的app
(venv) [root@master /data/blog]#cp manage.py myapp.py
cp: overwrite `myapp.py'? y
(venv) [root@master /data/blog]#vim myapp.py 
if __name__ == '__main__':
    app.debug = True
    app.run(host = '0.0.0.0', port = 8080)

#测试可以正常运行    
(venv) [root@master /data/blog]#/data/blog/venv/bin/gunicorn -c /data/blog/gunicorn.py myapp:app

(venv) [root@master /data/blog]#service supervisord restart

#创建模拟用户和文章 
#管理员由保存在设置变量FLASKY_ADMIN中的电子邮件地址识别,只要这个电子邮件地址出现在注册请求中,就会被赋予正确的角色
(venv) [root@master /data/blog]#python manage.py shell
User.generate_fake(100)
Post.generate_fake(1000)
  

nginx来代理
server {
    listen 80;
    server_name example.org; # 这是HOST机器的外部域名,用地址也行

    location / {
        proxy_pass http://127.0.0.1:8080; # 这里是指向 gunicorn host 的服务地址
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}  
  
  


当没有supversor
将 Gunicorn 作为服务运行
这就是最后一步了,我们在此将采用 UpStart 配置Flask程序作为服务程序在Linux起动时运行。首先建立起动配置文件:

sudo nano /etc/init/myflask.conf
然后加入如下配置

description "The myflask service"

start on runlevel [2345]
stop on runlevel [!2345]


respawn
setuid root
setgid www-data

env PATH= /var/www/myflask/venv/bin
chdir /var/www/myflask/

exec gunicorn -w 4 -b 127.0.0.1:8080 wsgi:application
sudo service myflask start

这里有一点必须补充的,请留意在 myflask.conf 中的
env PATH= /var/www/myflask/venv/bin
chdir /var/www/myflask/
这里所指向的地址就是你的项目路径和 virtualenv 的路径

未经允许不得转载:江哥架构师笔记 » python学习:flask + gunicorn + supervisor + nginx

分享到:更多 ()

评论 抢沙发

评论前必须登录!