Flask+gremlin-python+uWSGI部署时出现无当前事件循环报错问题
问题原因
- 你遇到的报错本质是
gremlinpython 3.4.x的DriverRemoteConnection底层依赖asyncio实现网络通信,asyncio默认只会为主线程自动创建事件循环,uWSGI spawn出来的处理请求的工作子线程没有默认绑定的事件循环,调用close()方法时尝试获取当前线程事件循环失败就会抛出该错误。 - 单元测试使用
test_client时所有逻辑都运行在主线程,自带默认事件循环,所以不会触发报错。 - 你对Flask
g对象的理解是正确的,问题和g的生命周期无关。
可行解决方案
方案1:为工作线程主动初始化事件循环(改动最小)
在_db_connect方法中新增事件循环初始化逻辑,确保每个处理请求的线程都有绑定的事件循环:
import asyncio from flask import Flask, g from gremlin_python.structure.graph import Graph from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection from gremlin_python.process.anonymous_traversal import traversal app = Flask(__name__, instance_relative_config=True) @app.before_request def _db_connect(): if not hasattr(g, 'graph_conn'): # 新增事件循环初始化逻辑 try: asyncio.get_event_loop() except RuntimeError: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) g.graph_conn = DriverRemoteConnection(app.config['DATABASE_HOST'],'g') g.gg = traversal().withRemote(g.graph_conn) @app.teardown_appcontext def _db_close(exc): if hasattr(g, 'graph_conn'): g.graph_conn.close() del g.graph_conn
同时在你的uWSGI配置中新增enable-threads = true配置,确保uWSGI不会限制子线程的异步逻辑运行:
[uwsgi] http = 0.0.0.0:3031 manage-script-name = true module = dogmaserver:app processes = 4 threads = 2 offload-threads = 2 stats = 0.0.0.0:9191 enable-threads = true # 新增配置
方案2:复用数据库连接(性能更优)
你当前每次请求新建、关闭连接的逻辑性能消耗很高,DriverRemoteConnection本身是线程安全的,可以全局复用,只需调整加载逻辑适配uWSGI的多进程模式:
- 新增uWSGI配置
lazy-apps = true,让每个uWSGI工作进程独立初始化应用,避免跨进程复用连接导致异常 - 调整代码逻辑,全局初始化连接,不用每次请求建连关连:
from flask import Flask, g from gremlin_python.structure.graph import Graph from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection from gremlin_python.process.anonymous_traversal import traversal app = Flask(__name__, instance_relative_config=True) # 全局初始化连接,每个uWSGI子进程会独立创建一份 graph_conn = DriverRemoteConnection(app.config['DATABASE_HOST'],'g') gg = traversal().withRemote(graph_conn) # 不需要再用before_request和teardown_appcontext管理连接生命周期
内容的提问来源于stack exchange,提问作者cts
相关产品推荐
相关产品推荐

