204 lines
7.6 KiB
Python
204 lines
7.6 KiB
Python
import eventlet
|
||
import logging
|
||
|
||
# 配置 eventlet 日志,抑制 IOClosed 等错误日志
|
||
logging.getLogger('eventlet.hubs').setLevel(logging.CRITICAL)
|
||
logging.getLogger('eventlet.greenio').setLevel(logging.CRITICAL)
|
||
|
||
# 进行猴子补丁操作
|
||
eventlet.monkey_patch()
|
||
|
||
# 配置 eventlet 以更优雅地处理错误,避免疯狂报错
|
||
try:
|
||
import eventlet
|
||
import traceback
|
||
|
||
# 1. 首先,禁用 eventlet 的调试日志,减少输出
|
||
import logging
|
||
logging.getLogger('eventlet').setLevel(logging.CRITICAL)
|
||
logging.getLogger('socketio').setLevel(logging.CRITICAL)
|
||
logging.getLogger('werkzeug').setLevel(logging.CRITICAL)
|
||
|
||
# 2. 配置 eventlet 相关设置(移除了不存在的debug属性)
|
||
|
||
# 3. 避免重复打印相同错误的机制
|
||
seen_errors = set()
|
||
max_error_logs = 5 # 每个错误最多打印5次
|
||
error_counts = {}
|
||
|
||
def is_duplicate_error(e):
|
||
"""检查是否为重复错误"""
|
||
error_key = f"{type(e).__name__}: {e}"
|
||
if error_key in seen_errors:
|
||
error_counts[error_key] = error_counts.get(error_key, 0) + 1
|
||
if error_counts[error_key] > max_error_logs:
|
||
return True
|
||
else:
|
||
seen_errors.add(error_key)
|
||
error_counts[error_key] = 1
|
||
return False
|
||
|
||
# 4. 只修改关键的 greenio 方法,确保在致命错误时彻底关闭连接
|
||
from eventlet import greenio
|
||
|
||
# 保存并替换原始的 greenio 方法
|
||
if hasattr(greenio.base.GreenSocket, '_recv_loop'):
|
||
original_recv_loop = greenio.base.GreenSocket._recv_loop
|
||
|
||
def custom_recv_loop(self, recv_func, recv_args, *args, **kwargs):
|
||
try:
|
||
return original_recv_loop(self, recv_func, recv_args, *args, **kwargs)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet IO Error] _recv_loop: {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底关闭连接,不再继续处理
|
||
try:
|
||
self.close()
|
||
except Exception:
|
||
pass
|
||
return b''
|
||
|
||
greenio.base.GreenSocket._recv_loop = custom_recv_loop
|
||
|
||
if hasattr(greenio.base.GreenSocket, 'recv_into'):
|
||
original_recv_into = greenio.base.GreenSocket.recv_into
|
||
|
||
def custom_recv_into(self, buffer, nbytes=0, flags=0):
|
||
try:
|
||
return original_recv_into(self, buffer, nbytes, flags)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet IO Error] recv_into: {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底关闭连接,不再继续处理
|
||
try:
|
||
self.close()
|
||
except Exception:
|
||
pass
|
||
return 0
|
||
|
||
greenio.base.GreenSocket.recv_into = custom_recv_into
|
||
|
||
if hasattr(greenio.base.GreenSocket, '_send_loop'):
|
||
original_send_loop = greenio.base.GreenSocket._send_loop
|
||
|
||
def custom_send_loop(self, send_func, data, *args, **kwargs):
|
||
try:
|
||
return original_send_loop(self, send_func, data, *args, **kwargs)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet IO Error] _send_loop: {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底关闭连接,不再继续处理
|
||
try:
|
||
self.close()
|
||
except Exception:
|
||
pass
|
||
return 0
|
||
|
||
greenio.base.GreenSocket._send_loop = custom_send_loop
|
||
|
||
if hasattr(greenio.base.GreenSocket, 'send'):
|
||
original_send = greenio.base.GreenSocket.send
|
||
|
||
def custom_send(self, data, flags=0):
|
||
try:
|
||
return original_send(self, data, flags)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet IO Error] send: {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底关闭连接,不再继续处理
|
||
try:
|
||
self.close()
|
||
except Exception:
|
||
pass
|
||
return 0
|
||
|
||
greenio.base.GreenSocket.send = custom_send
|
||
|
||
# 5. 处理 WSGI 中的错误,确保彻底清理
|
||
try:
|
||
import eventlet.wsgi
|
||
|
||
if hasattr(eventlet.wsgi.HttpProtocol, 'handle_one_request'):
|
||
original_wsgi_handle_one_request = eventlet.wsgi.HttpProtocol.handle_one_request
|
||
|
||
def custom_wsgi_handle_one_request(self):
|
||
try:
|
||
return original_wsgi_handle_one_request(self)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet WSGI Request Error] {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底清理连接,不再继续
|
||
try:
|
||
self.rfile.close()
|
||
self.wfile.close()
|
||
self.finish()
|
||
except Exception:
|
||
pass
|
||
return
|
||
|
||
eventlet.wsgi.HttpProtocol.handle_one_request = custom_wsgi_handle_one_request
|
||
|
||
if hasattr(eventlet.wsgi.HttpProtocol, 'handle_one_response'):
|
||
original_wsgi_handle_one_response = eventlet.wsgi.HttpProtocol.handle_one_response
|
||
|
||
def custom_wsgi_handle_one_response(self):
|
||
try:
|
||
return original_wsgi_handle_one_response(self)
|
||
except Exception as e:
|
||
if not is_duplicate_error(e):
|
||
print(f"[Eventlet WSGI Response Error] {type(e).__name__}: {e}")
|
||
print("[Traceback]")
|
||
traceback.print_exc()
|
||
# 彻底清理连接,不再继续
|
||
try:
|
||
self.rfile.close()
|
||
self.wfile.close()
|
||
self.finish()
|
||
except Exception:
|
||
pass
|
||
return
|
||
|
||
eventlet.wsgi.HttpProtocol.handle_one_response = custom_wsgi_handle_one_response
|
||
except Exception as e:
|
||
# 如果修改失败,忽略错误
|
||
print(f"[WSGI Patch Error] {e}")
|
||
|
||
print("[Eventlet Error Handling] Configured to handle errors gracefully, avoiding duplicate logs")
|
||
except Exception as e:
|
||
# 如果修改失败,打印错误但继续运行
|
||
print(f"[Eventlet Patch Initialization Error] {e}")
|
||
traceback.print_exc()
|
||
|
||
from flask import Flask
|
||
from .views.routes import main_bp
|
||
from .views.file import file_bp
|
||
from .config import Config
|
||
from .extensions import init_extensions,register_namespaces
|
||
|
||
def create_app():
|
||
app = Flask(__name__, template_folder="../templates", static_folder="../static",static_url_path="/vsc-like/static")
|
||
app.config.from_object(Config)
|
||
@app.route('/')
|
||
def hello():
|
||
return 'Hello, World!'
|
||
|
||
# 注册蓝图
|
||
app.register_blueprint(main_bp)
|
||
app.register_blueprint(file_bp)
|
||
# 初始化SocketIO
|
||
init_extensions(app)
|
||
|
||
register_namespaces(app)
|
||
|
||
return app
|