文章目录
- 一、安装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 配置
- 六、运维
- 6.1 启动gunicorn服务
- 6.2 停止gunicorn服务
一、安装python&使用虚拟环境
参见Arch Linux 定时运行python脚本(crontab)
二、python程序重要参数加密
2.1 非对称加密(RSA)
用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个的秘密性质。称公开的密钥为公钥;不公开的密钥为私钥。
参考“公钥加密”
- 生成RSA密钥对
- 私钥存储在服务器上(运维人员做好秘钥管理)
- 公钥公开给开发人员,用于代码中进行重要配置加密
2.2 生成密钥对
安装pycryptodome
pip install pycryptodome
from Crypto.PublicKey import RSA
key = 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
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
from flask import Flask, render_template
app = 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
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
# **运行配置**
# 并行工作进程数
workers = 4
# 指定每个工作者的线程数
threads = 2
# 使用nginx反向代理,默认本地访问端口 9999
bind = '127.0.0.1:9999'
## 修改是否重新加载
#reload = True
#
#daemon = True
## 超时时间,默认30
timeout=30
worker_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';
# MIME
include mime.types;
default_type application/octet-stream;
# logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# load configs
include /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
。
六、运维
6.1 启动gunicorn服务
文件名:start
#!/bin/bash
if [ "$#" -lt 1 ]; then
echo "Please provide one argument."
else
source ../bin/activate
python -m gunicorn --check-config $1
python -m gunicorn -c gunicorn.conf.py $1 -D
deactivate
fi
[rebecca@study src]$. start my_first_flask:app
6.2 停止gunicorn服务
文件名:stop
#!/bin/bash
head -n 1 gunicorn.pid | xargs kill -TERM
[rebecca@study src]$. stop