Linux部署python web项目Flask + gunicorn + nginx

news/2024/12/22 15:34:18/

文章目录

  • 一、安装python&使用虚拟环境
  • 二、python程序重要参数加密
    • 2.1 非对称加密(RSA)
    • 2.2 生成密钥对
    • 2.4 以连接数据库参数加密为例
      • 2.4.1 工具类RSA.py
  • 三、一个简单的Flask项目
  • 四、安装配置gunicorn
  • 4.1 安装
    • 4.2 启动/配置(选择eventlet)
      • 4.2.1 命令行方式配置参数
      • 4.2.2 配置文件方式配置参数
  • 五、安装配置nginx
    • 5.1 安装
    • 5.2 配置
  • 六、运维

python_2">一、安装python&使用虚拟环境

参见Arch Linux 定时运行python脚本(crontab)

python_4">二、python程序重要参数加密

2.1 非对称加密(RSA)

用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个的秘密性质。称公开的密钥为公钥;不公开的密钥为私钥。
参考“公钥加密”

  • 生成RSA密钥对
  • 私钥存储在服务器上(运维人员做好秘钥管理)
  • 公钥公开给开发人员,用于代码中进行重要配置加密

2.2 生成密钥对

安装pycryptodome

pip install pycryptodome
python">from Crypto.PublicKey import RSAkey = RSA.generate(2048)
private_key = key.export_key()
with open("private.pem", "wb") as f:f.write(private_key)public_key = key.publickey().export_key()
with open("public.pem", "wb") as f:f.write(public_key)

2.4 以连接数据库参数加密为例

【RSA加密/解密】PKCS1_OAEP和PKCS1_v1_5

2.4.1 工具类RSA.py

python">from Crypto.Cipher import PKCS1_OAEP as PKCS1_cipher
from Crypto.PublicKey import RSA
# 读取密钥
def get_key(path):with open(path) as f:pem_data = f.read()return RSA.importKey(pem_data)
# 公钥加密
def encrypt(msg, pub_path):key = get_key(pub_path)cipher = PKCS1_cipher.new(key)encrypt_msg = cipher.encrypt(msg.encode("utf-8"))return base64.b64encode(encrypt_msg).decode()
# 私钥加密
def decrypt(msg, pri_path):key = get_key(pri_path)cipher = PKCS1_cipher.new(key)decrypt_data = cipher.decrypt(base64.b64decode(msg))return decrypt_data.decode("utf-8")if __name__ == '__main__':original_msg = "hello world"encrypted_data = encrypt(original_msg, "./pub_key.pem")print("encrypt_data:", encrypted_data)decrypted_data = decrypt(encrypted_data, "./pri_key.pem")print("decrypt_data:", decrypted_data)

三、一个简单的Flask项目

pip install Flask

my_first_flask.py

python">from flask import Flask, render_templateapp = Flask(__name__, template_folder="template")@app.route("/t/hello")
def hello_world():return "<p>Hello, World!</p>"
@app.route("/t/index")
def index():return render_template('index.html')

template/index.html

<h1>index</h1>

gunicorn_92">四、安装配置gunicorn

4.1 安装

Web项目开启异步workers

$ pip install gunicorn
# web 项目必须启用 Async Workers(使用eventlet)
$ pip install greenlet            # Required for both
$ pip install eventlet            # For eventlet workers
# web 项目必须启用 Async Workers(使用gevent)
$ pip install greenlet            # Required for both
$ pip install gevent              # For gevent workers

4.2 启动/配置(选择eventlet)

参考博客
配置说明-官网

4.2.1 命令行方式配置参数

# 运行
# -k 配置使用workers 默认sync(同步),异步根据不同安装选择eventlet/gevent
nohup python -m gunicorn -w 5 -k eventlet -b 0.0.0.0:9999 -t 120 my_first_flask:app >> my_first_flask.log 2>&1 &# 根据进程号优雅关闭
kill -TERM 13078

4.2.2 配置文件方式配置参数

在这里插入图片描述
gunicorn.conf.py

python">
# **运行配置**# 并行工作进程数
workers = 4# 指定每个工作者的线程数
threads = 2# 使用nginx反向代理,默认本地访问端口 9999
bind = '127.0.0.1:9999'## 修改是否重新加载
#reload = True#
#daemon = True## 超时时间,默认30
timeout=30worker_class='eventlet'# **日志文件配置**
#loglevel="info"
#accesslog="log/access.log"
#errorlog="log/error.log"
logconfig_dict = {'version':1,'disable_existing_loggers': True,"root": {"level": "INFO", "handlers": ["root_handler"]},'loggers':{"gunicorn.error": {"level": "INFO",# 打日志的等级可以换的,下面的同理"handlers": ["error_file"], # 对应下面的键"propagate": 1,"qualname": "gunicorn.error"},"gunicorn.access": {"level": "DEBUG","handlers": ["access_file"],"propagate": 0,"qualname": "gunicorn.access"}},'handlers':{"error_file": {"class": "logging.handlers.RotatingFileHandler","backupCount": 3,# "when":"D",# "interval":1,"maxBytes": 1024 * 1024 * 10,"formatter": "generic","encoding": "utf-8","filename": "log/gunicorn.error.log"},"access_file": {"class": "logging.handlers.TimedRotatingFileHandler","backupCount": 3,"when":"D","interval":1,"formatter": "generic","filename": "log/gunicorn.access.log",},"root_handler":{"class": "logging.handlers.TimedRotatingFileHandler","backupCount": 3,"when":"D","interval":1,"formatter": "generic","filename": "log/gunicorn.root.log",}},'formatters':{"generic": {"format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", # 打日志的格式"datefmt": "[%Y-%m-%d %H:%M:%S %z]",# 时间显示方法"class": "logging.Formatter"},"access": {"format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'","class": "logging.Formatter"}}
}
# gunicorn当前的process id
pidfile="gunicorn.pid"

日志配置参照

五、安装配置nginx

5.1 安装

(1)使用包管理工具

# 安装
sudo pacman -S nginx# 验证是否安装成功
nginx -v
# 查看当前是否启动nginx(有master,worker)
ps -ef | grep nginx
# 查看当前nginx状态
systemctl status nginx
# 立即启动
systemctl start nginx
# 立即重启
systemctl restart nginx
# 设置开机自启动

(2)使用源码编译(TODO)

5.2 配置

/etc/nginx/nginx.conf

user http;
worker_processes auto;
worker_cpu_affinity auto;events {multi_accept on;worker_connections 1024;
}http {charset utf-8;sendfile on;tcp_nopush on;tcp_nodelay on;server_tokens off;log_not_found off;types_hash_max_size 4096;client_max_body_size 16M;log_format test 'upstat=$upstream_status';# MIMEinclude mime.types;default_type application/octet-stream;# loggingaccess_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log warn;# load configsinclude /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;    server {listen 9888;server_name 172.XXX.XXX.XXX;location /test/ {proxy_pass http://localhost:9999/t/;}error_page 400 401 402 403 404 405 406 407 408 409 /40x.html;location = /40x.html {root /usr/share/nginx/html;}access_log /var/log/nginx/access_test.log test;}
}

假设本机ip地址为:172.XXX.XXX.XXX。
访问:172.XXX.XXX.XXX:9888/test/path1,重定向到localhost:9999/t/path1
访问:172.XXX.XXX.XXX:9888/test/hello,重定向到localhost:9999/t/hello

六、运维

gunicorn_290">6.1 启动gunicorn服务

文件名:start

#!/bin/bashif [ "$#" -lt 1 ]; thenecho "Please provide one argument."
elsesource ../bin/activatepython -m gunicorn --check-config $1 python -m gunicorn -c gunicorn.conf.py $1 -Ddeactivate
fi
[rebecca@study src]$. start my_first_flask:app

gunicorn_309">6.2 停止gunicorn服务

文件名:stop

#!/bin/bashhead -n 1 gunicorn.pid | xargs kill -TERM 
[rebecca@study src]$. stop

http://www.ppmy.cn/news/1530832.html

相关文章

网络爬虫到底难在哪里?

如果你是自己做爬虫脚本开发&#xff0c;那确实难&#xff0c;因为你需要掌握Python、HTML、JS、xpath、database等技术&#xff0c;而且还要处理反爬、动态网页、逆向等情况&#xff0c;不然压根不知道怎么去写代码&#xff0c;这些技术和经验储备起码得要个三五年。 比如这几…

中国蚁剑(antSword)安装使用

antSword下载 antSword-Loader下载 作者&#xff1a;程序那点事儿 日期&#xff1a;2024/09/12 19:35 中国蚁剑&#xff08;AntSword&#xff09;是一款跨平台的开源网站管理工具&#xff0c;旨在满足渗透测试人员的需求。它是一个功能强大的工具&#xff0c;可以帮助用户管理…

python sqlite3数据库介绍(如何使用参数化查询防止SQL注入攻击)(直接通过网络让其他主机访问某台主机上的SQLite数据库是不被直接支持的)

文章目录 使用 Python 操作 SQLite 数据库1. 连接到 SQLite 数据库2. 创建表3. 插入数据4. 查询数据5. 关闭连接 安全性和最佳实践使用参数化查询&#xff1a;防止 SQL 注入攻击。如何工作Python 示例好处 关闭连接&#xff1a;在数据库操作完成后确保关闭连接。异常处理&#…

用 CSS 动画记录宝宝0-280天的变化

用 CSS 动画记录宝宝0-280天的变化 用动画记录宝宝从0-280天在肚子里的变化~ <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1…

了解云计算工作负载保护的重要性,确保数据和应用程序安全

云计算de小白 云计算技术的快速发展使数据和应用程序安全成为一种关键需求&#xff0c;而不仅仅是一种偏好。随着越来越多的客户公司将业务迁移到云端&#xff0c;保护他们的云工作负载&#xff08;指所有部署的应用程序和服务&#xff09;变得越来越重要。云工作负载保护&…

【github remote: Access denied等问题的通用解决方案】

第一步 查看Git所有配置&#xff08;杂七杂八的啥都有&#xff0c;看看即可&#xff09; $ git config --list 删除全部配置文件&#xff1a; $ git config --global --edit 然后输入 i&#xff0c;进行删除&#xff08;git bash中需右键复制剪贴&#xff09; 然后按esc进入命…

Python类里引用其他类

Python类里引用其他类 引言 在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;使用类的组合与继承是一种常见的设计模式。通过一个类引用另一个类&#xff0c;可以实现更复杂和灵活的功能&#xff0c;使得代码更加模块化和可重用。本文将介绍如何在Python中创建多个类…

mysql学习教程,从入门到精通,SQL INNER JOIN 语句(22)

1、SQL INNER JOIN 语句 SQL INNER JOIN 语句&#xff0c;首先需要明确你的数据库中有哪些表以及你想要通过哪些字段将它们关联起来。假设我们有两个表&#xff1a;employees&#xff08;员工表&#xff09;和departments&#xff08;部门表&#xff09;。employees 表包含员工…