您的当前位置:首页正文

flask项目生产环境部署:ngnix、gunicorn和supervisor安装配置

2024-11-29 来源:个人技术集锦

1、安装:
    pip3 install gunicorn
    pip3 install greenlet #使用异步必须安装
    pip3 install eventlet #使用eventlet workers
    pip3 install gevent   #使用gevent workers
    
2、配置https访问:
    gunicorn --certfile='/root/dongzhihang/certificate/1_dongzhihang.top_bundle.crt'  --keyfile='/root/dongzhihang/certificate/2_dongzhihang.top.key' -w 4 -b 0.0.0.0:4321 mainFlask:app
    后台启动:
    nohup gunicorn --certfile='/root/dongzhihang/certificate/1_dongzhihang.top_bundle.crt'  --keyfile='/root/dongzhihang/certificate/2_dongzhihang.top.key' -w 4 -b 0.0.0.0:4321 mainFlask:app  > $PWD/log_1029 2>&1 &

gunicorn 配置文件启动示例:

supervisor配置文件:(放入supervisor配置文件目录,一般是/etc/supervisor/)
[program:xxx-server] # 项目名称
command=/usr/local/python3/bin/gunicorn -c gun.py manage:app # 前面是gunicorn的绝对路径,后面的gun.py是gunicorn的配置文件, manage是你的flask项目启动文件名称
directory=/www/xxx-server # flask项目存放路径
autorestart=true
stdout_logfile=/www/server/log/mock-server.out.log # 日志
redirect_stderr=true
user=root
priority=999

gun.py配置文件:(gun.py放入directory指定的目录下即可)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/11/19 14:24
# @Author  : Weiqiang.long
# @Site    :
# @File    : gun.py
# @Software: PyCharm
# @Description:
# import requests
import os
import platform
import gevent.monkey
import multiprocessing


gevent.monkey.patch_all()
debug = True
loglevel = 'deubg'
# 服务地址(adderes:port)
bind = '0.0.0.0:8090'


if platform.system() == 'Windows':
    # win机器路径
    log_path = os.path.join(os.path.dirname(__file__), 'log')
else:
    # 服务器路径
    log_path = '/log'


# print(log_path)
pidfile = log_path + '/gunicorn.pid'
logfile = log_path + '/debug.log'


# 启动的进程数(获取服务器的cpu核心数*2+1)
workers = multiprocessing.cpu_count() * 2 +1
worker_class = 'gunicorn.workers.ggevent.GeventWorker'


threads = 20
preload_app = True
reload = True


x_forwarded_for_header = 'X-FORWARDED-FOR'

相关报错:
1、-bash: gunicorn: command not found

2、-bash: echo_supervisord_conf: command not found

tar -zxvf  supervisor-4.2.1.tar.gz  -C   /root/software/supervisor
cd /root/software/supervisor/supervisor-4.2.1
python3 setup.py install

验证是否安装成功:echo_supervisord_conf。若报错,参照下文步骤2

centos上安装,上步可能会报错。解决办法详见下篇博客

 yum install libffi-devel -y
 cd /root/software/python38/Python-3.8.0
 make&make install

2、配置:
(1)生成配置文件:

执行命令:cd /root/software/supervisor/supervisor-4.2.1
python3 setup.py install安装时,如下路径即为安装路径

vim ~/.bashrc

export PATH=$PATH:/root/software/python38/Python-3.8.0/bin

source ~/.bashrc


(2)初次启动:
    supervisord -c /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf
    注意:启动后会在supervisord.conf指定的路径(pidfile=/root/customer/supervisord_conf/supervisord.pid)生成2个文件:supervisord.pid、supervisor.sock。

   上述启动方式,是修改了/root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf文件里supervisord.pid、supervisor.sock、supervisord.log 文件路径,注意下。
    如果在supervisord.conf修改了supervisord.pid、supervisor.sock文件路径,要重新执行(2),直接执行supervisorctl reload,会报错:unix:///tmp/supervisor.sock no such file

#############################################################

为了方便管理:

/root/software/supervisor/supervisor-4.2.1/conf/user

#############################################################

supervisord -c /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf

上述方式启动时,直接用supervisorctl status会报错:error: , [Errno 113] No route to host: file: /root/software/python38/Python-3.8.0/lib/python3.8/socket.py line: 796。

要用:

supervisorctl -c /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf status
supervisorctl -c /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf reload    //修改了程序,重新启动,要用reload,用restart不行

    supervisord : 启动supervisor
    supervisorctl reload :修改完配置文件后重新启动supervisor
    supervisorctl status :查看supervisor监管的进程状态
    supervisorctl start 进程名 :启动XXX进程
    supervisorctl stop 进程名 :停止XXX进程
    supervisorctl stop all:停止全部进程,注:start、restart、stop都不会载入最新的配置文件。
    supervisorctl update:根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启

(8)设置开机启动:
    vim /etc/init.d/supervisord
    
    添加以下脚本:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          supervisord
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

# Author: Dan MacKinlay <danielm@phm.gov.au>
# Based on instructions by Bertrand Mathieu
# http://zebert.blogspot.com/2009/05/installing-django-solr-varnish-and.html

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin
DESC="Description of the service"
NAME=supervisord
DAEMON=/usr/local/bin/supervisord
DAEMON_ARGS=" -c /etc/supervisord.conf"
#PIDFILE=/var/run/$NAME.pid
PIDFILE=/tmp/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
        $DAEMON_ARGS \
        || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  #reload|force-reload)
    #
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" "$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
esac

# 设置该脚本为可以执行
    sudo chmod +x /etc/init.d/supervisord

    若是ubuntu:
        # 设置为开机自动运行
        sudo update-rc.d supervisord defaults
    若是centos:
        centos设置开机自动启动:
        chkconfig supervisord  on
        centos关闭开机自动启动:
        chkconfig sshd off
        
    # 试一下,是否工作正常
    service supervisord stop
    service supervisord start

(9)配置浏览器管理:
vim /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf
配置 inet_http_server
[inet_http_server]       
port=127.0.0.1:9001     ; 服务器ip
username=xxx        ;自定义
password=xxx        ;自定义

(10)常用报错解决办法:

supervisorctl -c /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf reload命令重启报如下错:

error: , [Errno 111] Connection refused: file: /root/software/python38/Python-3.8.0/lib/python3.8/site-packages/supervisor-4.2.1-py3.8.egg/supervisor/xmlrpc.py line: 560

解决办法:

将supervisord.pid、supervisor.sock这2个文件删除,执行命令:supervisord -c   /root/software/supervisor/supervisor-4.2.1/conf/supervisord.conf重新生成配置文件,执行该命令同时也会启动,不用在reload。

注意是supervisord命令,不是supervisorctl

三、ngnix安装配置:

1、安装ngnix:

yum -y install nginx

若报错:No package nginx available.

解决办法:

出现这个的原因是因为本地中没有我们想要的nginx,那么我们就需要创建一个/etc/yum.repos.d/nginx.repo的文件,新增一个yum源。

# vi /etc/yum.repos.d/nginx.repo

#在文件中写入以下内容

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

2、修改ngnix配置:

cd /etc/nginx/   ,vi  ngnix.conf

配置如下,

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
		server_name  www.*****.com;   #填自己的域名
	#return 301 https://$server_name$request_uri;
	#return https://$server_name:2591$request_uri;  #跳转到外部网站
    
	
	location / {
        proxy_pass https://0.0.0.0:1234; #挑战到本机的其它端口:转发到本机的1234端口,即转发给gunicorn 
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
		
    }

	# Settings for a TLS enabled server.

    server {
        
	listen       443 ssl;
	server_name  www.****.top;
		
	
	# ssl证书地址
	ssl_certificate     /***/***/***.pem;
	ssl_certificate_key  /***/***/***.key;
	
	# ssl验证相关配置
	ssl_session_timeout  5m;    #缓存有效期
	ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    #加密算法
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;    #安全链接可选的加密协议
	ssl_prefer_server_ciphers on;   #使用服务器端的首选算法
	
	#return https://$server_name:2591$request_uri;
	
	location / {
        proxy_pass https://0.0.0.0:1234; #转发到本机的1234端口,即转发给gunicorn
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme; # fix flask redirect生产环境 从https到http跳转
    }
	
    }

}

3、将ngnix交给supervisor管理

cd /etc/supervisor  ,  vi ngnix.conf

command = /usr/sbin/nginx 这个命令默认是后台启动,但是supervisor不能监控后台程序。加上-g ‘daemon off;‘这个参数可解决这问题,这个参数的意思是在前台运行。

4、ngnix常用命令:

一、ngnix管理命令
1、配置文件路径:
cd /etc/nginx/

2、错误日志:
tail -f /var/log/nginx/error.log

3、重启:
service nginx restart
systemctl start nginx.service
systemctl restart nginx.service


4、停止服务:
nginx -s quit
nginx -s stop
killall nginx

5、杀死占用80端口的进程
sudo fuser -k 80/tcp

6、查看ngnix安装目录:
which nginx
nginx -V
more /etc/init.d/nginx

7、查看ngnix服务:
ps aux | grep nginx

8、当有系统配置文件有修改,用此命令,建议不要停止再重启,以防报错!
nginx -s reload

显示全文