11.25 超时设置、连接设置
This commit is contained in:
parent
0fc892f819
commit
80df0e377a
@ -1,7 +1,8 @@
|
||||
import threading
|
||||
import time
|
||||
from functools import wraps
|
||||
from flask import current_app, jsonify, stream_with_context, Response
|
||||
from flask import current_app, jsonify, stream_with_context, Response, request
|
||||
|
||||
|
||||
class ExecutionTimeoutMonitor:
|
||||
"""监控请求执行时间,超时后释放信号量"""
|
||||
@ -26,17 +27,21 @@ class ExecutionTimeoutMonitor:
|
||||
self.thread.start()
|
||||
|
||||
def require_connection_limit(timeout=900):
|
||||
"""装饰器:确保路由使用连接限制,并监控请求执行时间"""
|
||||
def decorator(f):
|
||||
@wraps(f)
|
||||
def wrapped(*args, **kwargs):
|
||||
limiter = getattr(current_app, 'connection_limiter', None)
|
||||
blueprint = request.blueprint
|
||||
limiter = current_app.connection_limiters.get(blueprint, current_app.connection_limiters.get('default'))
|
||||
if limiter is None:
|
||||
current_app.logger.error("ConnectionLimiter 未初始化")
|
||||
return jsonify({'error': 'Server configuration error'}), 500
|
||||
current_app.logger.error(f"未为蓝图 '{blueprint}' 配置 ConnectionLimiter,并且未设置默认限流器。")
|
||||
return jsonify({'error': '服务器配置错误'}), 500
|
||||
|
||||
# 获取信号量(阻塞)
|
||||
acquired = limiter.semaphore.acquire(blocking=True)
|
||||
if not acquired:
|
||||
current_app.logger.warning("并发连接过多")
|
||||
return jsonify({'error': '并发连接过多'}), 429
|
||||
|
||||
# 阻塞方式获取信号量
|
||||
limiter.semaphore.acquire()
|
||||
try:
|
||||
# 启动执行超时监控器
|
||||
monitor = ExecutionTimeoutMonitor(timeout, limiter.semaphore)
|
||||
@ -49,8 +54,7 @@ def require_connection_limit(timeout=900):
|
||||
try:
|
||||
for item in generator:
|
||||
if monitor.is_timeout:
|
||||
# 如果已超时,终止生成器执行
|
||||
current_app.logger.error("Request exceeded execution time and was terminated.")
|
||||
current_app.logger.error("请求执行时间超过限制并被终止。")
|
||||
break
|
||||
yield item
|
||||
finally:
|
||||
@ -60,8 +64,8 @@ def require_connection_limit(timeout=900):
|
||||
return Response(generator_wrapper(), mimetype='text/event-stream')
|
||||
except Exception as e:
|
||||
limiter.semaphore.release() # 异常时释放信号量
|
||||
current_app.logger.error(f"Exception in route: {e}")
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
||||
current_app.logger.error(f"路由处理异常: {e}")
|
||||
return jsonify({'error': '内部服务器错误'}), 500
|
||||
return wrapped
|
||||
return decorator
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
# flask_app/routes/get_deviation.py
|
||||
import time
|
||||
|
||||
from flask import Blueprint, request, jsonify, Response, stream_with_context, g
|
||||
import json
|
||||
@ -6,13 +7,11 @@ import os
|
||||
from flask_app.main.download import download_file
|
||||
from flask_app.general.post_processing import outer_post_processing
|
||||
from flask_app.general.接口_技术偏离表 import get_tech_and_business_deviation
|
||||
|
||||
from flask_app.logger_setup import CSTFormatter
|
||||
|
||||
from flask_app.routes.utils import generate_deviation_response, validate_request
|
||||
|
||||
from flask_app.ConnectionLimiter import require_connection_limit
|
||||
get_deviation_bp = Blueprint('get_deviation', __name__)
|
||||
@get_deviation_bp.route('/get_deviation', methods=['POST'])
|
||||
@require_connection_limit(timeout=700)
|
||||
def get_deviation():
|
||||
logger = g.logger
|
||||
unique_id = g.unique_id
|
||||
|
@ -1,9 +1,11 @@
|
||||
# flask_app/routes/little_zbparse.py
|
||||
import time
|
||||
|
||||
from flask import Blueprint, request, jsonify, Response, stream_with_context, g
|
||||
import json
|
||||
import os
|
||||
|
||||
from flask_app.ConnectionLimiter import require_connection_limit
|
||||
from flask_app.main.download import download_file
|
||||
from flask_app.general.post_processing import outer_post_processing
|
||||
from flask_app.general.接口_小解析 import little_parse_main
|
||||
@ -14,6 +16,7 @@ from flask_app.routes.utils import validate_request
|
||||
|
||||
little_zbparse_bp = Blueprint('little_zbparse', __name__)
|
||||
@little_zbparse_bp.route('/little_zbparse', methods=['POST'])
|
||||
@require_connection_limit(timeout=300)
|
||||
def little_zbparse():
|
||||
logger = g.logger
|
||||
file_url, zb_type = validate_request()
|
||||
|
@ -17,7 +17,7 @@ from flask_app.ConnectionLimiter import require_connection_limit
|
||||
upload_bp = Blueprint('upload', __name__)
|
||||
|
||||
@upload_bp.route('/upload', methods=['POST'])
|
||||
@require_connection_limit(timeout=900)
|
||||
@require_connection_limit(timeout=800)
|
||||
def zbparse():
|
||||
logger = g.logger
|
||||
try:
|
||||
@ -38,7 +38,6 @@ def zbparse():
|
||||
except Exception as e:
|
||||
logger.error('Unexpected exception: ' + str(e))
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
||||
|
||||
def process_and_stream(file_url, zb_type):
|
||||
"""
|
||||
下载文件并进行处理,支持工程标和货物标的处理。
|
||||
|
@ -13,7 +13,8 @@ from flask_app.routes.test_zbparse import test_zbparse_bp
|
||||
class FlaskAppWithLimiter(Flask):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.connection_limiter = ConnectionLimiter(max_connections=10)
|
||||
# 初始化一个字典来存储每个蓝图的限流器
|
||||
self.connection_limiters = {}
|
||||
def create_app():
|
||||
app = FlaskAppWithLimiter(__name__)
|
||||
|
||||
@ -47,7 +48,9 @@ def create_app():
|
||||
app.register_blueprint(little_zbparse_bp)
|
||||
app.register_blueprint(upload_bp)
|
||||
app.register_blueprint(test_zbparse_bp)
|
||||
|
||||
app.connection_limiters['upload'] = ConnectionLimiter(max_connections=7)
|
||||
app.connection_limiters['get_deviation'] = ConnectionLimiter(max_connections=7)
|
||||
app.connection_limiters['default'] = ConnectionLimiter(max_connections=10)
|
||||
return app
|
||||
|
||||
#TODO:培训要求、总体要求、进度要求、'建设要求'到技术要求中,归类到其他要求中
|
||||
|
Loading…
x
Reference in New Issue
Block a user