Bottle 中部署应用程序的整个流程及相关配置
Python Web 部署结构
对于生产环境来说,部署 Python Web 应用程序基本上需要用到 Web 服务器和 WSGI 服务器。那么它们是如何连接的呢?如下图所示:
这里Web服务器用于接受客户端的http请求,然后返回处理后的结果。对于Python Web应用程序来说,目前主流的是Nginx,它占用内存少,并发能力强,在同类型的Web服务器之间性能更好。
WSGI的全称是Python Web Server Gateway Interface,用于连接Web服务器和Python Web开发框架。目前常用的是uWSGI和gunicorn。
Web应用大多是基于框架完成的。对于python来说,主要框架有Django、Flask和Tornado,主要用于实现业务层逻辑,不关注http层的具体内容。
Flask应用的部署推荐方式是:Nginx + Gunicorn + Flask,下面详细介绍。
Gunicorn
Gunicorn 是一种广泛使用的高性能 Python HTTP 服务器,仅支持 UNIX 环境。 Gunicorn 采用 pre-fork 工作模式,可以与各种 wsgi Web 框架配合使用。
那么你为什么需要一只枪呢?首先,如果使用Flask内置的WSGI,由于它运行在单进程中,处理请求的能力有限,一般用于测试。 Gunicorn 还支持WSGI的服务。同时,得益于预分叉工作模式,worker启动后会开发出指定数量的应用进程。多个进程处理的请求数肯定高于单个进程处理的请求数。另外,gunicorn接受nginx转发的http请求,收到处理后的响应后转发给nginx。
1)安装
pip install gunicorn # 安装最新版本
pip install gunicorn==19.9.0 # 安装指定版本
# 如果异步,需要安装对应模块
pip install eventlet # 使用eventlet工作模式
pip install gevent # gevent工作模式
2)运行gunicorn
gunicorn [options] main_app:app
main_app是银行应用main_app.py的主模块,app是应用实例的名称,必须与中的应用实例的名称一致代码。
选项是参数。常用的有:
- -k/--worker-class:指定工作模式。可选参数:
- -w/--workers:输入应用进程数,默认为1
- -b/--bind:输入客户端地址,HOST:PORT 格式,例如 -b 127.0.0.1:8000
- - t/--threads:每个进程处理请求的线程数。默认值是每个工作线程一个线程。指定线程的工作模式自动更改为gthread模式;
- --worker-connections:工作线程连接数,默认为1000,仅在eventlet和gevent工作模式下有效
- -t/--timeout超时时间,默认为30秒,工作进程将被杀死并重新启动,如果他没有在规定的时间内做出回应。
- --reload=True,当代码更改时重新启动gunicorn
- -D, --daemon:将gunicorn作为后台进程运行
- --log-level:指定日志输出级别- -logfile :访问日志输出文件
- --error-logfile:错误日志文件输出
注:
a。参数格式:-p值,--params=值
b。工作模式 当指定为 gevent 或 Evenlet 时,threads 参数无效
常用的启动命令,后面的 main 是应用程序输入模块 main.py 的名称
# 指定worker数量gunicorn -w 5 -b 127.0.0.1:8080 main:app
# 设置线程
gunicorn -w 5 -t 2 -b 127.0.0.1:8080 main:app
# 设置异步工作模式
gunicorn --worker-class=gevent \
--worker-connections=1000 \
-w 3 main:app
3)工作模式选择
- gunicorn 同步模式默认情况下。在此模式下,每个工作线程一次仅处理一个请求。只有处理完成后才能处理下一个请求。在高并发场景下会消耗大量的CPU和内存。
- 异步有两种模式:gevent和evenlet。在异步模式下,工作进程可以同时处理多个请求,而不会阻塞其他请求。
- 如果没有阻塞响应,请使用同步工作线程。如果阻塞较多,则使用异步模式;建议使用(2*CPU)+1作为worker数量。
4) 结束进程
第一次使用:ps -ef | grep Gunicorn命令找出gunicorn主进程ID
然后执行:kill -9主进程ID。当主进程被杀死时,其他子进程也会自动被杀死。您可以稍后再次运行搜索命令进行确认。
Nginx部署
Nginx是一个轻量级的Web服务器/反向代理服务器。它的主要用途是:
- 作为反向代理客户端请求Nginx,Nginx请求应用服务器。然后将结果返回给客户端
- 进行负载均衡,大量用户请求分配到多台计算机上处理
- 静动分离,静态请求直接从设置的根路径获取对应的资源nginx 服务器,动态请求转发到后台处理
- 成为虚拟主机,将多个网站部署到一台服务器
1) 安装
apt install nginx # ubuntu
yum install nginx # Centos
2) 启动/停止 Nginx
sudo nginx # 启动
sudo nginx -s reload # 热启动
sudo nginx -s stop # 停止
sudo pkill -9 nginx # 强制停止
3)查看 nginx 启动状态
Start :systemctl status nginx,运行状态如下图:
4) Nginx 配置
以 Ubuntu20.04 为例,nginx /etc 目录配置如下:
site-available 为有效站点配置,default为默认配置;
sites-enabled 是当前使用的站点配置,实际上是指向sites-available站点中的配置的软链接。以下示例展示了如何配置。
首先在站点可用的目录中,将默认设置复制到flask_demo,然后修改flask_demo的配置如下:
server {
listen 9000 default_server;
listen [::]:9000 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
proxy_pass http://127.0.0.1:9001;
}
服务器配置对应使用nginx作为反向代理的站点,9000是Nginx端口,proxy_pass是绑定地址和gunicorn服务端口。
然后进入允许站点的目录,创建配置软连接:
sudo ln -s /etc/nginx/sites-available/flask_demo flask_demo
测试下面的简单银行应用程序:
模块名称为app.py,内容如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Testing Flask App Deployment"
运行Guni在浏览器中搜索目标地址。这里192.168.56.106是当前测试虚拟机的IP地址,9000是刚刚配置的Nginx端口。内容如下:
5)负载均衡配置
为了分散单台服务器的访问压力或者将业务划分转化为微服务,一般采用服务器集群部署方式。但如果服务器对应的是域名,外部访问肯定会不方便。我们应该做什么? Nginx负载均衡可以解决这个问题。下图是负载均衡结构示意图:
在Nginx服务器配置中添加不同的服务器地址,然后进行反向代理。对于外部用户来说,他们不知道有多台后端服务器,访问的域名也不会发生变化。
此外,还可以通过负载均衡来配置主从服务器。当主机出现故障时,nginx将请求发送到备份服务器进行处理。
以下是实现负载均衡的简单示例:
注:由于资源有限,测试始终在一台电脑上进行。其实每个应用都部署在单独的虚拟机或者dock上
- 首先复制两份flask应用,重命名并修改URL,返回app.py文件信息,方便对比;
- 使用gunicorn 启动这两个新应用程序。地址仍然是127.0.0.1,端口是9002和9003;
- 打开配置文件:sudo vim /etc/nginx/sites-available/flask_demo
- 将应用服务的地址添加到“上游域”配置项中,并在如图所示的位置编辑proxy_pass的内容如下代码:
upstream domain {
server localhost:9001;
server localhost:9002;
server localhost:9003;
}
server {
listen 9000 default_server;
listen [::]:9000 default_server;
# 此处省略原注释配置项若干行
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
proxy_pass http://domain;
proxy_set_header Host $host:$server_port;
}
- 保存 错误正确后,执行: sudo nginx -s reload 然后在浏览器中测试不同服务的URL。结果如下:
测试根路径:
Test/app1:
Test/app2:
从内容看,地址和端口没有改变,不同的URL代表不同的服务;反映到后端时,实际访问的是不同服务器上的应用程序,从而实现负载均衡。
总结
通过以上内容和示例,我们了解了部署瓶装应用的整个流程以及相关配置。实际项目中,配置比较复杂。这里只是做一个介绍。如果想深入了解原理,建议查看官方文档或者其他特殊内容...
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。