文章目录
说个问题
自己写了一个Python小程序,传入一定参数就有一定的输出,现在想开放给所有人在线使用,如何搭建服务器以及如何处理用户的请求和响应???
写个方案
存在多种方案,作者采用的是Gunicorn配合Nginx,用户访问Nginx服务器,Nginx反向代理将请求传给Gunicorn,Gunicorn调用Python应用程序,应用程序处理后将结果回传Gunicorn,Gunicorn传递给Nginx,Nginx最后响应给用户。
一、安装Ubuntu Server
参考文章:【SH】VMware虚拟机安装Ubuntu Server 24系统研发笔记
二、安装Web服务器
采用Nginx服务器
在线文档和支持:http://nginx.org/
也可以采用Apache,作者经过详细了解和异同点比较之后选择了Nginx,Nginx更加轻量级,资源消耗更少,静态文件(如HTML、图片、CSS等直接从磁盘读取的内容)处理更加高效,配置更加简单。而动态文件可以反向代理将动态请求转发给后端的应用程序服务器处理(如uWSGI)。
- 更新软件包索引,确保索引是最新的,
sudo apt update
sh@sheephero:~$ sudo apt update
[sudo] password for sh:
Hit:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble InRelease
Get:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates InRelease [126 kB]
Get:3 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-backports InRelease [126 kB]
Hit:4 http://security.ubuntu.com/ubuntu noble-security InRelease
Fetched 252 kB in 1s (189 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
66 packages can be upgraded. Run 'apt list --upgradable' to see them.
N: Missing Signed-By in the sources.list(5) entry for 'http://mirrors.tuna.tsinghua.edu.cn/ubuntu'
N: Missing Signed-By in the sources.list(5) entry for 'http://mirrors.tuna.tsinghua.edu.cn/ubuntu'
- 用apt包管理器安装Nginx,
sudo apt install nginx
sh@sheephero:~$ sudo apt install nginx
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
nginx-common
Suggested packages:
fcgiwrap nginx-doc ssl-cert
The following NEW packages will be installed:
nginx nginx-common
0 upgraded, 2 newly installed, 0 to remove and 66 not upgraded.
Need to get 552 kB of archives.
After this operation, 1,596 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/main amd64 nginx-common all 1.24.0-2ubuntu7.1 [31.2 kB]
Get:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/main amd64 nginx amd64 1.24.0-2ubuntu7.1 [521 kB]
Fetched 552 kB in 1s (1,071 kB/s)
Preconfiguring packages ...
Selecting previously unselected package nginx-common.
(Reading database ... 83751 files and directories currently installed.)
Preparing to unpack .../nginx-common_1.24.0-2ubuntu7.1_all.deb ...
Unpacking nginx-common (1.24.0-2ubuntu7.1) ...
Selecting previously unselected package nginx.
Preparing to unpack .../nginx_1.24.0-2ubuntu7.1_amd64.deb ...
Unpacking nginx (1.24.0-2ubuntu7.1) ...
Setting up nginx (1.24.0-2ubuntu7.1) ...
Setting up nginx-common (1.24.0-2ubuntu7.1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
Processing triggers for ufw (0.36.2-6) ...
Processing triggers for man-db (2.12.0-4build2) ...
Scanning processes...
Scanning linux images...
Running kernel seems to be up-to-date.
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
- 启动Nginx服务并检查其状态,启动:
sudo systemctl start nginx
查看状态:sudo systemctl status nginx
sh@sheephero:~$ sudo systemctl start nginx
sh@sheephero:~$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2024-12-16 01:06:56 UTC; 9min ago
Docs: man:nginx(8)
Process: 3273 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 3275 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 3276 (nginx)
Tasks: 3 (limit: 4556)
Memory: 2.4M (peak: 2.5M)
CPU: 11ms
CGroup: /system.slice/nginx.service
├─3276 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─3277 "nginx: worker process"
└─3279 "nginx: worker process"
Dec 16 01:06:56 sheephero systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 16 01:06:56 sheephero systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.
- 打开浏览器,输入服务器的IP地址和端口(端口默认80),如果看见Nginx的欢迎界面,说明安装成功!😀🎉
三、安装Python及依赖
Ubuntu Server 24系统自带Python3,查看安装版本:python3 --version
sh@sheephero:~$ python3 --version
Python 3.12.3
但是没有安装venv依赖,需要安装: apt install python3.12-venv
sh@sheephero:~$ sudo apt install python3.12-venv
[sudo] password for sh:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
python3-pip-whl python3-setuptools-whl
The following NEW packages will be installed:
python3-pip-whl python3-setuptools-whl python3.12-venv
0 upgraded, 3 newly installed, 0 to remove and 66 not upgraded.
Need to get 2,424 kB of archives.
After this operation, 2,771 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/universe amd64 python3-pip-whl all 24.0+dfsg-1ubuntu1.1 [1,703 kB]
Get:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/universe amd64 python3-setuptools-whl all 68.1.2-2ubuntu1.1 [716 kB]
Get:3 http://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/universe amd64 python3.12-venv amd64 3.12.3-1ubuntu0.3 [5,678 B]
Fetched 2,424 kB in 1s (3,600 kB/s)
Selecting previously unselected package python3-pip-whl.
(Reading database ... 83799 files and directories currently installed.)
Preparing to unpack .../python3-pip-whl_24.0+dfsg-1ubuntu1.1_all.deb ...
Unpacking python3-pip-whl (24.0+dfsg-1ubuntu1.1) ...
Selecting previously unselected package python3-setuptools-whl.
Preparing to unpack .../python3-setuptools-whl_68.1.2-2ubuntu1.1_all.deb ...
Unpacking python3-setuptools-whl (68.1.2-2ubuntu1.1) ...
Selecting previously unselected package python3.12-venv.
Preparing to unpack .../python3.12-venv_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking python3.12-venv (3.12.3-1ubuntu0.3) ...
Setting up python3-setuptools-whl (68.1.2-2ubuntu1.1) ...
Setting up python3-pip-whl (24.0+dfsg-1ubuntu1.1) ...
Setting up python3.12-venv (3.12.3-1ubuntu0.3) ...
Scanning processes...
Scanning linux images...
Running kernel seems to be up-to-date.
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
安装Python及依赖(已安装可省略)
sudo apt install python3 python3-pip python3-venv
创建项目虚拟环境
- 选择一个合适的目录用于存放项目文件,并在该目录中创建Python虚拟环境
mkdir dip_project && cd dip_project
- 为了管理项目的依赖,很有必要每个项目创建一个虚拟环境:
python3 -m venv dipenv
- 激活Python虚拟环境
source dipenv/bin/activate
激活后,终端提示符会变为(dipenv),表示当前正在使用虚拟环境。source命令是Ubuntu中bash shell的一个内置命令,用于在当前shell环境中读取并执行某个文件中的命令。退出虚拟环境:deactivate
sh@sheephero:~/dip_project$ source dipenv/bin/activate
(dipenv) sh@sheephero:~/dip_project$
四、安装Python Web框架
采用Flask框架
参考文档:https://pypi.org/project/Flask/
也可以采用Django框架,作者经过详细了解和异同点比较之后选择了Flask,Flask更加轻量级且灵活,适合初学者和开发小型应用程序,核心功能简单,但也可以通过扩展实现强大功能。
- 在激活的虚拟环境中,使用pip安装Flask,
pip install flask
(dipenv) sh@sheephero:~/dip_project$ pip install Flask
Collecting Flask
Downloading flask-3.1.0-py3-none-any.whl.metadata (2.7 kB)
Collecting Werkzeug>=3.1 (from Flask)
Downloading werkzeug-3.1.3-py3-none-any.whl.metadata (3.7 kB)
Collecting Jinja2>=3.1.2 (from Flask)
Downloading jinja2-3.1.4-py3-none-any.whl.metadata (2.6 kB)
Collecting itsdangerous>=2.2 (from Flask)
Downloading itsdangerous-2.2.0-py3-none-any.whl.metadata (1.9 kB)
Collecting click>=8.1.3 (from Flask)
Downloading click-8.1.7-py3-none-any.whl.metadata (3.0 kB)
Collecting blinker>=1.9 (from Flask)
Downloading blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)
Collecting MarkupSafe>=2.0 (from Jinja2>=3.1.2->Flask)
Downloading MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)
Downloading flask-3.1.0-py3-none-any.whl (102 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 103.0/103.0 kB 352.3 kB/s eta 0:00:00
Downloading blinker-1.9.0-py3-none-any.whl (8.5 kB)
Downloading click-8.1.7-py3-none-any.whl (97 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 97.9/97.9 kB 1.6 MB/s eta 0:00:00
Downloading itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Downloading jinja2-3.1.4-py3-none-any.whl (133 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 133.3/133.3 kB 2.1 MB/s eta 0:00:00
Downloading werkzeug-3.1.3-py3-none-any.whl (224 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 224.5/224.5 kB 2.8 MB/s eta 0:00:00
Downloading MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (23 kB)
Installing collected packages: MarkupSafe, itsdangerous, click, blinker, Werkzeug, Jinja2, Flask
Successfully installed Flask-3.1.0 Jinja2-3.1.4 MarkupSafe-3.0.2 Werkzeug-3.1.3 blinker-1.9.0 click-8.1.7 itsdangerous-2.2.0
(dipenv) sh@sheephero:~/dip_project$
- 验证安装:
python -m flask --version
如果安装成功,会显示Flask的版本信息
(dipenv) sh@sheephero:~/dip_project$ python -m flask --version
Python 3.12.3
Flask 3.1.0
Werkzeug 3.1.3
创建和运行Flask应用(以后的重点)
- 创建和运行Flask应用,在项目目录里面新建一个【app.py】文件
vim app.py
,写入如下内容(IP地址就是Ubuntu的地址):
# save this as app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
if __name__ == '__main__':
app.run(host='172.16.37.37', port=5000)
保存后,运行如下命令:python app.py
,使之处于监听状态。
(dipenv) sh@sheephero:~/dip_project$ python app.py
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://172.16.37.37:5000
Press CTRL+C to quit
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.警告:这是一个开发服务器。不要用于生产环境。请使用生产WSGI服务器代替。
- 打开客户机的浏览器,访问虚拟机的服务器,在浏览器中输入
http://172.16.37.37:5000
来查看Flask应用的输出
五、安装WSGI服务器
WSGI服务器,用于Web服务器反向代理Python程序。
uWSGI和Gunicorn都是Web服务器,实现了WSGI(Web Server Gateway Interface)协议,用于接收请求并分发给后端应用(如Django或Flask)。
采用Gunicorn
也可以安装uWSGI,作者经过详细了解和异同点比较之后选择了Gunicorn,Gunicorn配置相对简单,易于上手。它遵循“Keep it simple and stupid”(KISS)的设计理念,提供了一个稳定且易于维护的Web服务器环境。
- 在项目虚拟环境中安装gunicorn,
(dipenv) sh@sheephero:~/dip_project$ pip install gunicorn
Collecting gunicorn
Downloading gunicorn-23.0.0-py3-none-any.whl.metadata (4.4 kB)
Collecting packaging (from gunicorn)
Downloading packaging-24.2-py3-none-any.whl.metadata (3.2 kB)
Downloading gunicorn-23.0.0-py3-none-any.whl (85 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 85.0/85.0 kB 305.7 kB/s eta 0:00:00
Downloading packaging-24.2-py3-none-any.whl (65 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 65.5/65.5 kB 1.2 MB/s eta 0:00:00
Installing collected packages: packaging, gunicorn
Successfully installed gunicorn-23.0.0 packaging-24.2
- 重新使用Gunicorn运行Flask应用(假设Flask应用名为app.py,且应用实例名为app),根据上文编写的app.py文件来输入命令
gunicorn --workers 4 --bind 0.0.0.0:6758 app:app
,这条命令会启动Gunicorn,并监听所有网络接口上的6758端口。
【–workers 4】这个选项指定了Gunicorn应该启动的工作进程数量。在这个例子中,它被设置为4。工作进程是实际处理请求的Python进程。增加工作进程的数量可以提高你的应用处理并发请求的能力,但是也会增加内存和CPU的使用。
【–bind 0.0.0.0:6758】这个选项告诉Gunicorn监听哪个IP地址和端口上的连接。0.0.0.0是一个特殊的IP地址,表示监听所有可用的网络接口。这意味着,如果你的服务器有多个IP地址(例如,一个内网地址和一个外网地址),你的应用将能够在所有这些地址上接受连接。6758是端口号,是应用将监听以接受连接的TCP端口。
【app:app】这部分指定了要运行的WSGI应用。它通常遵循模块名:应用对象名的格式。在这个例子中,app是Python模块的名字,而第二个app是该模块中定义的WSGI应用对象的名字。这意味着你的应用应该有一个名为app.py的文件,里面有一个名为app的Flask(或其他WSGI兼容框架)应用实例。
(dipenv) sh@sheephero:~/dip_project$ gunicorn --workers 4 --bind 0.0.0.0:6758 app:app
[2024-12-16 13:28:27 +0000] [25695] [INFO] Starting gunicorn 23.0.0
[2024-12-16 13:28:27 +0000] [25695] [INFO] Listening at: http://0.0.0.0:8000 (25695)
[2024-12-16 13:28:27 +0000] [25695] [INFO] Using worker: sync
[2024-12-16 13:28:27 +0000] [25696] [INFO] Booting worker with pid: 25696
[2024-12-16 13:28:27 +0000] [25697] [INFO] Booting worker with pid: 25697
[2024-12-16 13:28:27 +0000] [25698] [INFO] Booting worker with pid: 25698
[2024-12-16 13:28:28 +0000] [25699] [INFO] Booting worker with pid: 25699
六、配置Nginx
配置Nginx以转发请求给Gunicorn
- 备份Nginx的默认配置文件:
(dipenv) sh@sheephero:/etc/nginx/sites-available$ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
(dipenv) sh@sheephero:/etc/nginx/sites-available$ tree -L 3
.
├── default
└── default.bak
1 directory, 2 files
- 编辑Nginx的配置文件:
sudo vim /etc/nginx/sites-available/default
- 在配置文件中添加或修改以下内容,以将请求转发给Gunicorn,your_server_ip_or_domain替换为你的服务器IP地址或域名:
server {
listen 80;
server_name your_server_ip_or_domain;
location / {
proxy_pass http://127.0.0.1:6758;
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;
}
}
- 测试Nginx配置文件的正确性:
sudo nginx -t
(dipenv) sh@sheephero:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
- 重启Nginx服务以应用更改:
sudo systemctl restart nginx
七、验证部署
启动Gunicorn保持监听,启动Nginx服务,然后通过浏览器输入http://172.16.37.37
访问服务:
八、扩展
编写POST请求
请看下一篇文章:【SH】基于Python Web应用的Flask Web开发学习笔记