我们知道利用flask模块进行服务部署时间很简单的事情,但是flask模块本身是用于开发适用,而不是用于生产环境中。例如在下面这张图片就可以看出在启动flask会有相应警告。
flask server.png
因为在工作中用到了这方面内容,因此在这里做一个总结,记录一下服务简单部署的方法。在这里我们分为三个部分:
- flask 部署
- uwsgi部署
- 监控部署
通过启动uwsgi
来启动flask 服务.
文件路径
├── src
│ ├── server.py
│ ├── check_server.py
│ │ │ ├──ini
│ │ │ │ ├── uwsgi.ini
1. flask 部署
文件1: server.py
import flask
FLASK_HOST = params_config.get('flask', 'host')
api_name = params_config.get('flask', 'api_name')
FLASK_PORT = params_config.getint('flask', 'port')
app = flask.Flask(__name__)
@app.route('/quit', methods=['POST', 'GET'])
def kill():
# do something
return ''
@app.route('/restart', methods=['POST', 'GET'])
def restart():
# do something
return ''
@app.route('/{}'.format(api_name), methods=['POST', 'GET'])
def color_cluster():
"""
This function is a main entrance of this server
"""
try:
# do some thing
return result
except Exception as e:
return ''
if __name__ == '__main__':
app.run(host=FLASK_HOST, port=FLASK_PORT)
2. uwsgi配置
文件2:uwsgi.ini
这里需要说明的是这里的配置是针对flask, 有些针对django配置会有些不一样。这里给出uwsgi中文文档详细参数可以参考这里的官方文档uwsgi中文官方文档。
[uwsgi]
daemonize = myapp_uwsgi.log
http=:7010
chdir=/data/project/color_extraction/code/src
pythonpath=/data/models-master/research:/data/models-master/research/slim
pythonpath=/data/models-master/research/object_detection/utils
wsgi-file=/data/project/color_extraction/code/src/color_extraction_server.py
callable = app
processes=50
threads=1
master=True
safe-pidfile=%(chdir)/ini/uwsgi.pid
参数介绍如下:
-
daemonize
:加上这个参数就可以将uwsgi放入后台运行,并将日志打印到此日志文件中去 -
http
:这里写明端口号 -
chdir
: 这里写上程序根目录(即server.py
文件所在目录)对应上述目录结构为src
-
pythonpath
:python环境变量 -
wsgi-file
: 启动服务地址,在这里是server.py
-
callable
: 对于flask一定要写上,否则会报callable not found or import error错误 -
process
: 这里写上process 进程数目 -
thread
: 这里写上thread线程数。警告
:这里写上进程数目的时候,线程最好写 1 因为我在测试的时候,发现线程数目不为 1 时候,服务吞吐量会下降 -
master
: 允许主线程存在。此时的master写为True 否则会自动启动一个僵尸进程 -
safe-pidfile
: 这里会打印主线程pid到此文件中去(可以利用此pid做监控,所以建议保留此参数)
3. 监控程序
这里会做一个心跳监控,并实时将服务状态发送到钉钉报警群中。
import os
import socket
import time
import psutil
import subprocess
import dingtalk_chatbot
from config_load import params_config
web_hook = params_config.get('check_server', 'web_hook') # dingding 报警群web_hook id
sleep_time = params_config.getint('check_server', 'sleep_time') # 每多长时间检测一次服务状态
server_name = params_config.get("check_server", "server_name") # 服务名称
start_uwsgi_cmd = params_config.get("check_server", "start_uwsgi_cmd") # 启动uwsgi. 这里是uwsgi uwsgi.ini
def get_check_program_pid(process_name):
process = subprocess.Popen(['pgrep', '-f', process_name],
stdout=subprocess.PIPE, shell=False)
pid = process.communicate()[0]
return pid
def get_host_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()
return ip
machine_ip = get_host_ip()
def get_pid(pid_text_path):
with open(pid_text_path) as pid_text:
pid_num = int(pid_text.readlines()[-1])
return pid_num
def check_pid(pid_num):
if psutil.pid_exists(pid_num):
return True
else:
return False
def restart_server():
os.system(start_uwsgi_cmd)
pid_text_path = params_config.get("check_server", "pid_text_path")
time.sleep(3)
pid_num = get_pid(pid_text_path)
if check_pid(pid_num):
chat_bot.send_text('{}机器 - {}服务已重新启动@所有人'.format(machine_ip, server_name))
else:
chat_bot.send_text('{}机器 - {}服务启动失败@所有人'.format(machine_ip, server_name))
if __name__ == '__main__':
chat_bot = dingtalk_chatbot.DingtalkChatbot(web_hook)
machine_ip = get_host_ip()
msg = "{} 机器 - {}已部署启动".format(machine_ip, server_name)
time.sleep(3)
chat_bot.send_text(msg)
while True:
pid_text_path = params_config.get("check_server", "pid_text_path")
pid_num = get_pid(pid_text_path)
result = check_pid(pid_num)
if result:
msg = '{}机器 - {}服务正常运行,请放心!'.format(machine_ip, server_name)
chat_bot.send_text(msg)
else:
msg = '{}机器 - {}服务挂了! 正在重启...@所有人'.format(machine_ip, server_name)
chat_bot.send_text(msg)
restart_server()
time.sleep(sleep_time)
服务启动
-
服务启动:
我们只要去ini
文件夹下执行uwsgi uwsgi.ini
即能启动服务。 -
监控服务启动:
执行nohup python3 check_server.py
启动监控服务。
网友评论