Flask服务构建
本文记录flask服务构建结构,包括get和post请求区分,网页挂载方式,Gunicron的服务化。
项目构建
环境配置
安装flask,flask_restful,flask_cors,gunicron等模块。
文件结构
- _init_.py
- main.py
- pygun.py
- templates/
- index.html
- admin.html
- static/
- main.js
- styles.css
- icon.ico
_init_.py 用于初始化一些配置
from flask import Flask
from flask_restful import Api
from flask_cors import *
app = Flask(__name__)
CORS(app, supports_credentials=True)
app.debug = True
api = Api(app)
main.py 服务启动入口文件
# coding=utf-8
from __init__ import app, api
from flask_restful import Resource
from flask import render_template
@app.route("/")
def toWebRoot():
return render_template('index.html')
@app.route("/main")
def toWebMain():
return render_template('index.html')
@app.route("/admin")
def toWebAdmin():
return render_template('admin.html')
class connect(Resource):
def get(self):
return {"success": True, "message": "connected!"}
class UserGetIdResource(Resource):
def get(self, uid):
# print(uid)
return {'uid':uid}
api.add_resource(connect, '/connect') # 测试接口
api.add_resource(UserGetIdResource, '/user/<int:uid>') #传递可变参数
# @app.route("/hello", methods=['POST', 'GET'])
if __name__ == "__main__":
# pyinstaller -F main.py --noconsole
# gunicorn --workers=6 rpa_data_server:app -b 0.0.0.0:8010
'''
运行命令:
gunicorn -c pygun.py main:app --log-level=debug --preload
'''
serverPort = 8010
app.run(host="0.0.0.0",port=serverPort)
pygun.py gunicorn启动服务的配置文件
bind = '10.110.2.3:8010' #gunicorn监控的接口
workers = 3 #进程数
threads = 2 #每个进程开启的线程数
proc_name = 'app'
#gunicorn进程id,kill掉该文件的id,gunicorn就停止
# pidfile = '/data1/test/app.pid'
loglevel = 'debug' #warining
# logfile = '/data1/test/debug.log'
#错误信息日志
# errorlog = '/data/test/error.log'
timeout = 10
#https://github.com/benoitc/gunicorn/issues/1194
keepalive = 75 # needs to be longer than the ELB idle timeout
worker_class = 'gevent' # 工作模式协程
##about timeout issuses
#https://github.com/benoitc/gunicorn/issues/1440
#https://github.com/globaldigitalheritage/arches-3d/issues/54
#https://github.com/benoitc/gunicorn/issues/588
#https://github.com/benoitc/gunicorn/issues/1194
#https://github.com/benoitc/gunicorn/issues/942
#https://stackoverflow.com/questions/10855197/gunicorn-worker-timeout-error
worker_connections = 100 #最大并发量
#access日志配置,更详细配置请看:https://docs.gunicorn.org/en/stable/settings.html#logging
#`%(a)s`参考示例:'%(a)s "%(b)s" %(c)s' % {'a': 1, 'b' : -2, 'c': 'c'}
#如下配置,将打印ip、请求方式、请求url路径、请求http协议、请求状态、请求的user agent、请求耗时
#示例:[2020-08-19 19:18:19 +0800] [50986]: [INFO] 127.0.0.1 POST /test/v1.0 HTTP/1.1 200 PostmanRuntime/7.26.3 0.088525
access_log_format="%(h)s %(r)s %(s)s %(a)s %(L)s"
#https://github.com/benoitc/gunicorn/issues/2250
logconfig_dict = {
'version':1,
'disable_existing_loggers': False,
#在最新版本必须添加root配置,否则抛出Error: Unable to configure root logger
"root": {
"level": "DEBUG",
"handlers": ["console"] # 对应handlers字典的键(key)
},
'loggers':{
"gunicorn.error": {
"level": "DEBUG",# 打日志的等级;
"handlers": ["error_file"], # 对应handlers字典的键(key);
#是否将日志打印到控制台(console),若为True(或1),将打印在supervisor日志监控文件logfile上,对于测试非常好用;
"propagate": 0,
"qualname": "gunicorn_error"
},
"gunicorn.access": {
"level": "DEBUG",
"handlers": ["access_file"],
"propagate": 0,
"qualname": "access"
}
},
'handlers':{
"error_file": {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024*1024*1,# 打日志的大小(此处限制1mb)
"backupCount": 1,# 备份数量(若需限制日志大小,必须存在值,且为最小正整数)
"formatter": "generic",# 对应formatters字典的键(key)
"filename": "./logs/debug.log" #若对配置无特别需求,仅需修改此路径
},
"access_file": {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024*1024*1,
"backupCount": 1,
"formatter": "generic",
"filename": "./logs/access.log", #若对配置无特别需求,仅需修改此路径
},
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'generic',
},
},
'formatters':{
"generic": {
"format": "%(asctime)s [%(process)d]: [%(levelname)s] %(message)s", # 打日志的格式
"datefmt": "[%Y-%m-%d %H:%M:%S %z]",# 时间显示格式
"class": "logging.Formatter"
}
}
}
index.html 首页
两种js/css文件引入方式:
- src="static/main.js"
- src="{{ url_for('static', filename='main.js') }}"
<!DOCTYPE html><html lang="zh"><head>
<meta charset="utf-8">
<title>title</title>
<base href="./">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='icon.ico') }}">
<style>@charset "UTF-8";</style>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}"></noscript></head>
<body>
<app-root></app-root>
<script src="{{ url_for('static', filename='main.js') }}" type="module"></script>
</body></html>
flask传递流内容及前端分段获取
// npm install eventsource
var EventSource = require('eventsource')
var source = new EventSource("http://127.0.0.1:8000/stream", { withCredentials: true })
source.onmessage = function (event) {
console.log(event.data)
if (event.data >= 4) {
source.close()
}
}