python flask+uwsgi 服务部署+监控机制

我们知道利用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

参数介绍如下:

  1. daemonize:加上这个参数就可以将uwsgi放入后台运行,并将日志打印到此日志文件中去
  2. http:这里写明端口号
  3. chdir: 这里写上程序根目录(即server.py文件所在目录)对应上述目录结构为src
  4. pythonpath:python环境变量
  5. wsgi-file: 启动服务地址,在这里是server.py
  6. callable: 对于flask一定要写上,否则会报callable not found or import error错误
  7. process: 这里写上process 进程数目
  8. thread: 这里写上thread线程数。警告:这里写上进程数目的时候,线程最好写 1 因为我在测试的时候,发现线程数目不为 1 时候,服务吞吐量会下降
  9. master: 允许主线程存在。此时的master写为True 否则会自动启动一个僵尸进程
  10. 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 启动监控服务。

参考

  1. uwsgi参数参考

你可能感兴趣的:(python flask+uwsgi 服务部署+监控机制)