flask+uwsgi+docker+nginx 云服务器部署测试平台

flask+uwsgi+docker+nginx 云服务器部署测试平台

开发环境
本次主要是在腾讯云上进行部署,系统是CentOS 7.9 64位,主要使用的软件如下:

Python 3.9.5
Pycharm
Flask1.0.2
Mysql 5.7
nginx + uwsgi

一 安装Nginx

1.更新yum 源

sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

2.安装

sudo yum install nginx

3.配置nginx

// 1.设置开机启动
$ sudo systemctl enable nginx
// 2.启动服务
$ sudo systemctl start nginx
// 3.停止服务
$ sudo systemctl restart nginx
// 4.重新加载,因为一般重新配置之后,不希望重启服务,这时可以使用重新加载。
$ sudo systemctl reload nginx

4.docker部署

拉取镜像:docker pull nginx:1.17.9
构建容器 
docker run -d --name nginx -p 8081:80 
--privileged=true --restart always 
-v ${PWD}/nginx/html:/usr/share/nginx/html 
-v ${PWD}/nginx/logs:/var/log/nginx 
nginx:1.17.9

-v ${PWD}/nginx/conf/nginx.conf:/etc/nginx/nginx.conf 
不支持直接挂载文件,可以创建后复制到容器中

5.请求转发

配置nginx

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak 备份
sudo vim /etc/nginx/nginx.conf 编辑

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


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

    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;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

改为

 user  root;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


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

    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;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
    upstream flask {
    server 101.35.129.200:5001;
     }

    server {

      listen       80;
      server_name  localhost;  #改为自己的域名,如果没有域名就修改为127.0.0.1 或者 localhost
      location / {
         proxy_pass http://101.35.129.200:5001;  # 此处可以写单个主机信息(前面的gunicorn启动的ip地址),也可以写upstream的组名。
         # proxy_pass http://flask;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
     }
   }
}

访问

4.常见问题

// 绑定其他端口
// Nginx 默认绑定的端口是 http 协议的默认端口,端口号为:80,如果需要绑定其他端口,需要注意 SELinux 的配置

// 例如:绑定 8081 端口,但是会发现无法启动,一般的报错如下

// YYYY/MM/DD hh:mm:ss [emerg] 46123#0: bind() to 0.0.0.0:8081 failed (13: Permission denied)
// 此时需要更改 SELinux 的设置。我们使用 SELinux 的管理工具 semanage 进行操作,比较方便。

// 安装 semanage 使用如下命令

sudo yum install policycoreutils-python
// 然后查看是否有其他协议类型使用了此端口

sudo semanage port -l | grep 8081
transproxy_port_t              tcp      8081
// 返回了结果,表明已经被其他类型占用了,类型为 transproxy_port_t。

// 我们还要查看一下 Nginx 的在 SELinux 中的类型 http_port_t 绑定的端口

sudo semanage port -l | grep http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
// 第一行 http_port_t 中没有包含 8081 这个端口。因此需要修改 8081 端口到 http_port_t 类型中。

sudo semanage port -m -p tcp -t http_port_t 8081
// 如果没有其他协议类型使用想要绑定的端口,如 8001,则我们只要新增到 SELinux 中即可。

sudo semanage port -l | grep 8001
sudo semanage port -a -p tcp -t http_port_t 8001
// 此时,重新启动 Nginx 即可。

二 防火墙操作

1.查看已经开放的端口

firewall-cmd --list-ports

2.开启端口

firewall-cmd --zone=public --add-port=80/tcp --permanent

3.命令含义

–zone #作用域

–add-port=80/tcp #添加端口,格式为:端口/通讯协议

–permanent #永久生效,没有此参数重启后失效

4.重启防火墙

firewall-cmd --reload #重启firewall

systemctl stop firewalld.service #停止firewall

systemctl disable firewalld.service #禁止firewall开机启动

firewall-cmd --state #查看默认防火墙状态(关闭后

作者:Oort
链接:https://www.jianshu.com/p/8012323b60a2
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三 CentOS 7 安装 Python3.7

1.安装 Python3.7

yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel

这里面有一个包很关键libffi-devel,因为只有3.7才会用到这个包,如果不安装这个包的话,在 make 阶段会出现如下的报错:

ModuleNotFoundError: No module named '_ctypes'

2.安装pip,因为 CentOs 是没有 pip 的。

#运行这个命令添加epel扩展源 
yum -y install epel-release 
#安装pip 
yum install python-pip

3.可以用yum 安装 安装一下 wget

yum -y install wget

4.下载 python3.7的源码包

wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
#解压缩
tar -zxvf Python-3.7.0.tgz

#进入解压后的目录,依次执行下面命令进行手动编译
./configure prefix=/usr/local/python3 
make && make install

如果最后没提示出错,就代表正确安装了,在/usr/local/目录下就会有python3目录

5.添加软链接

#添加python3的软链接 
ln -s /usr/local/python3/bin/python3.7 /usr/bin/python3.7 
#添加 pip3 的软链接 
ln -s /usr/local/python3/bin/pip3.7 /usr/bin/pip3.7
#测试是否安装成功了 
python -V

6.更改yum配置,因为其要用到python2才能执行,否则会导致yum不能正常使用(不管安装 python3的那个版本,都必须要做的)

vi /usr/bin/yum 
把 #! /usr/bin/python 修改为 #! /usr/bin/python2 
vi /usr/libexec/urlgrabber-ext-down 
把 #! /usr/bin/python 修改为 #! /usr/bin/python2

7.docker安装python

Dockerfile

FROM python:3.6

LABEL maintainer="dasun"

USER root

ARG kdir=/home

WORKDIR $kdir

RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

#映射端口
EXPOSE 5000
CMD ["python -version"]

四 WSGI安装配置

1.WSGI是什么?

WSGI,全称 Web Server Gateway Interface,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。
WSGI就像是一座桥梁,一边连着web服务器,另一边连着用户的应用

2.uwsgi和uWSGI

uwsgi同WSGI一样是一种通信协议。
而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

为什么要使用

使用flask写了一个简易的http服务用来提供接口,按照接口文档demo写好以后本地测试一切正常,但是发布到服务器以后有一串警告:WARNING:This is a developnent server. Do not use it in a production deploynent,如下图:
在这里插入图片描述
意思是我的这个启动方式不能在生产环境上使用,然后带着疑问上网查了一下,我的启动方式是

app.run(host="0.0.0.0", port=80)

只适用于开发模式,因为它是单线程的,生产环境影响性能,替代方案是可以用uWSGI或者pywsgi

3.三者的区别如下

1.app.run 启动的是单线程服务,性能很低

2.pywsgi服务器使用的是gevent的pywsgi模块,性能不错,配置也很简单,但是它只是把单线程改造成了单线程异步方式

3.uWSGI性能最好,配置稍微比上面难一点,但是它是支持多进程、多线程、和多协程的方式,简直就是完美,所以我选择尝试使用uWSGI服务器来替代

4.pywsgi方式实现

1.安装gevent模块
pip install gevent

2.在启动类里引入模块
from gevent import pywsgi

3.main方法里将app.run替换
server = pywsgi.WSGIServer(('0.0.0.0', 80), app)
server.serve_forever()

5.uWSGI实现

官方文档 https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/WSGIquickstart.html#uwsgipython

5.1安装uWSGI模块
 pip install uwsgi
5.2配置文件

在根目录下创建uWSGI配置文件 【uwsgi.ini】

[uwsgi]
# 使用nginx连接时使用
# socket = 0.0.0.0:8080

# 地址端口 直接作为web服务器使用
http = 0.0.0.0:80
# 项目路径
chdir = /root/projectname
# 项目启动文件 适用于flask项目部署
wsgi-file = manage.py
# 项目需要调用的启动类 router
callable = app
# 进程线程设置
processes = 4
threads = 10
# 日志文件
daemonize = /app/logs/uwsgi.log
# 保存主进程pid文件
pidfile = uwsgi.pid
# 是否需要主进程
master = true
5.3相关命令
使用uwsgi服务器启动 : uwsgi --ini uwsgi.ini
停止 : uwsgi --stop uwsgi.pid
停止 : pkill -f uwsgi -9

uwsgi --http-socket :6005 --http-websockets --wsgi-file app.py --callable app --master --processes 4 --threads 2 --stats 127.0.0.1:9191
5.4配置选项
master = true  #启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。

chdir = /web/www/mysite  #在app加载前切换到当前目录, 指定运行目录

module = mysite.wsgi  # 加载一个WSGI模块,这里加载mysite/wsgi.py这个模块

py-autoreload=1  #监控python模块mtime来触发重载 (只在开发时使用)

lazy-apps=true  #在每个worker而不是master中加载应用

socket = /test/myapp.sock  #指定socket文件,也可以指定为127.0.0.1:9000,这样就会监听到网络套接字

processes = 2 #启动2个工作进程,生成指定数目的worker/进程

buffer-size = 32768   #设置用于uwsgi包解析的内部缓存区大小为64k。默认是4k。

daemonize = /var/log/myapp_uwsgi.log  # 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器

log-maxsize = 5000000 #设置最大日志文件大小

disable-logging = true #禁用请求日志记录

vacuum = true #当服务器退出的时候自动删除unix socket文件和pid文件。

listen = 120 #设置socket的监听队列大小(默认:100)

pidfile = /var/run/uwsgi.pid  #指定pid文件

enable-threads = true  #允许用内嵌的语言启动线程。这将允许你在app程序中产生一个子线程

reload-mercy = 8  #设置在平滑的重启(直到接收到的请求处理完才重启)一个工作子进程中,等待这个工作结束的最长秒数。这个配置会使在平滑地重启工作子进程中,如果工作进程结束时间超过了8秒就会被强行结束(忽略之前已经接收到的请求而直接结束)

max-requests = 5000  #为每个工作进程设置请求数的上限。当一个工作进程处理的请求数达到这个值,那么该工作进程就会被回收重用(重启)。你可以使用这个选项来默默地对抗内存泄漏

limit-as = 256  #通过使用POSIX/UNIX的setrlimit()函数来限制每个uWSGI进程的虚拟内存使用数。这个配置会限制uWSGI的进程占用虚拟内存不超过256M。如果虚拟内存已经达到256M,并继续申请虚拟内存则会使程序报内存错误,本次的http请求将返回500错误。

harakiri = 60  #一个请求花费的时间超过了这个harakiri超时时间,那么这个请求都会被丢弃,并且当前处理这个请求的工作进程会被回收再利用(即重启)

5.5运行
查看进程 : ps -aux | grep uwsgi
root     14281  0.4  2.3 272640 42000 ?        S    16:06   0:00 uwsgi --ini uwsgi.ini
root     14370  0.0  2.1 936228 37452 ?        Sl   16:06   0:00 uwsgi --ini uwsgi.ini
root     14371  0.0  2.1 936228 37456 ?        Sl   16:06   0:00 uwsgi --ini uwsgi.ini
root     14381  0.0  2.1 936228 37452 ?        Sl   16:06   0:00 uwsgi --ini uwsgi.ini
root     14382  0.0  2.1 936228 37456 ?        Sl   16:06   0:00 uwsgi --ini uwsgi.ini
root     14383  0.0  2.0 273124 37096 ?        S    16:06   0:00 uwsgi --ini uwsgi.ini
root     18126  0.0  0.0 112824   980 pts/0    S+   16:07   0:00 grep --color=auto uwsgi
S代表一个主进程, Sl代表四个子进程
常见问题总结
运行uwsgi时出错 open(“./python_plugin.so”)

运行uwsgi时出错:
open(“./python_plugin.so”): No such file or directory [core/utils.c line 3713]
UNABLE to load uWSGI plugin: ./python_plugin.so: cannot open shared object file: No such file or directory!
原因:这可能是uwsgi的配置问题
解决:1. 若是使用的uwsgi 的配置文件是 .ini 类型时,注释

# plugin = python
  1. 若是配置文件是 .xml 类型时,删除 python 。

  2. 其他配置文件类型还有 .json 及 .yaml 文件。

  3. 若是以上配置文件没问题,那么就是没有安装好 uwsgi 或者uwsgi 服务没有启动,启动uwsgi 服务:

systemctl start uwsgi
再次运行命令是否可行。若还是不可行,那么按照以下步骤:

首先查询是否已存在uwsgi,并卸载:

rpm -qa|grep uwsgi
yum remove -y uwsgi*
若之前是pip 安装的话,执行:

pip uninstall uwsgi
重新安装:

Ubuntu 的Python3 :

apt-get install -y uwsgi-plugin-python3
注:这里可能还有个所有可用的plugin:sudo apt-get install uwsgi-plugins-all

centos环境:

sudo yum install -y uwsgi-plugin-python
查看 uwsgi 服务是否启动:

systemctl status uwsgi
若没有则启动之。

server配置
from wsgiref.simple_server import make_server
server = make_server('127.0.0.1', 5000, app)
server.serve_forever()
app.run(host='127.0.0.1',port=5000)

Docker容器一起动就退出的解决方案
docker run -dit --name testplatformapi --network testplatform -p 5001:5001 testplatformapi:v1 /bin/bash
添加-it 参数交互运行
添加-d 参数后台运行
这样就能启动一个一直停留在后台运行的Centos了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值