Files
hsa/code-server-like/app/__init__.py

225 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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. 增强错误处理,确保所有绿色线程错误都被捕获
# 保存原始的 greenlet 主函数,包装它以捕获所有异常
import eventlet.greenthread
original_main = eventlet.greenthread.main
def custom_greenthread_main(*args, **kwargs):
"""包装 greenlet 主函数,捕获所有异常,防止服务器宕机"""
try:
return original_main(*args, **kwargs)
except Exception as e:
# 捕获所有绿色线程中的异常
if not is_duplicate_error(e):
print(f"[Eventlet GreenThread Error] {type(e).__name__}: {e}")
print("[Traceback]")
traceback.print_exc()
# 返回 None 继续运行,防止服务器宕机
return None
# 替换原始的 greenlet 主函数
eventlet.greenthread.main = custom_greenthread_main
# 5. 只修改关键的 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