默认关闭插件热加载扫盘监听

This commit is contained in:
liuwei
2026-05-06 11:07:47 +08:00
parent 831a61e7ea
commit b4c046a594
4 changed files with 51 additions and 2 deletions

View File

@@ -1,6 +1,14 @@
environment: "${ABOT_ENVIRONMENT:development}"
plugin_dir: "${ABOT_PLUGIN_DIR:plugins}"
plugin_hot_reload:
# 线上默认关闭插件热加载扫描:
# 1. 避免后台线程周期性扫盘;
# 2. 降低 discover_plugins 带来的额外 IO
# 3. 如确实需要热更新,再单独通过环境变量打开。
enabled: "${ABOT_PLUGIN_HOT_RELOAD_ENABLED:false}"
interval_seconds: "${ABOT_PLUGIN_HOT_RELOAD_INTERVAL:600}"
db_config:
pool_name: "${ABOT_DB_POOL_NAME:wechat_boot_pool}"
pool_size: "${ABOT_DB_POOL_SIZE:10}"

View File

@@ -1,6 +1,14 @@
environment: "${ABOT_ENVIRONMENT:development}"
plugin_dir: "${ABOT_PLUGIN_DIR:plugins}"
plugin_hot_reload:
# 线上默认关闭插件热加载扫描:
# 1. 避免后台线程周期性扫盘;
# 2. 降低 discover_plugins 带来的额外 IO
# 3. 如确实需要热更新,再单独通过环境变量打开。
enabled: "${ABOT_PLUGIN_HOT_RELOAD_ENABLED:false}"
interval_seconds: "${ABOT_PLUGIN_HOT_RELOAD_INTERVAL:600}"
db_config:
pool_name: "${ABOT_DB_POOL_NAME:wechat_boot_pool}"
pool_size: "${ABOT_DB_POOL_SIZE:10}"

View File

@@ -153,6 +153,20 @@ class Config(object):
except (TypeError, ValueError):
return default
@staticmethod
def _safe_bool(value, default: bool):
"""把常见的字符串/数字配置安全转成布尔值。"""
if value is None:
return default
if isinstance(value, bool):
return value
text = str(value).strip().lower()
if text in {"1", "true", "yes", "y", "on"}:
return True
if text in {"0", "false", "no", "n", "off"}:
return False
return default
def _normalize_config(self, yconfig: dict) -> dict:
"""对解析后的配置做一次结构与类型归一化。"""
normalized = copy.deepcopy(yconfig or {})
@@ -180,6 +194,15 @@ class Config(object):
email_config["smtp_port"] = self._safe_int(email_config.get("smtp_port", 465), 465)
normalized["email_config"] = email_config
plugin_hot_reload = dict(normalized.get("plugin_hot_reload", {}) or {})
# 插件热加载本质上是一个持续扫盘线程:
# 1. 本地开发时它很方便,但线上稳定运行时意义不大;
# 2. 用户当前明确希望先停掉这类自动扫盘行为,降低不必要的 IO 干扰;
# 3. 因此这里把 enabled / interval_seconds 做成标准化配置,便于后续按环境开关。
plugin_hot_reload["enabled"] = self._safe_bool(plugin_hot_reload.get("enabled", False), False)
plugin_hot_reload["interval_seconds"] = self._safe_int(plugin_hot_reload.get("interval_seconds", 600), 600)
normalized["plugin_hot_reload"] = plugin_hot_reload
return normalized
@classmethod
@@ -423,6 +446,7 @@ class Config(object):
# 后续如果逐步引入更严格的配置对象,也可以先不动业务代码。
self.environment = str(self.resolved_config.get("environment", "development") or "development").strip()
self.plugin_dir = str(self.resolved_config.get("plugin_dir", "plugins") or "plugins").strip()
self.plugin_hot_reload = self.resolved_config.get("plugin_hot_reload", {})
self.mariadb = self.resolved_config.get("db_config", {})
self.redis = self.resolved_config.get("redis_config", {})
self.email = self.resolved_config.get("email_config", {})

View File

@@ -115,8 +115,17 @@ class Robot:
self.plugin_manager = PluginManager(plugin_dir=getattr(self.config, "plugin_dir", "plugins"))
self.plugin_manager.set_system_context(self.system_context)
self.plugins = self.plugin_manager.load_all_plugins()
# 热加载改为低频扫描:每 60 秒检查一次插件文件变动
self.plugin_manager.start_hot_reload_watcher(interval_seconds=60.0)
# 插件热加载默认关闭:
# 1. 它会持续轮询插件目录并调用 discover_plugins线上运行会产生额外扫盘开销
# 2. 对当前以“稳定运行”为主的场景,这类自动热更新收益远低于成本;
# 3. 若后续确实需要在线调试插件,可通过配置重新打开,并把轮询间隔调大。
hot_reload_cfg = dict(getattr(self.config, "plugin_hot_reload", {}) or {})
if bool(hot_reload_cfg.get("enabled")):
interval_seconds = max(float(hot_reload_cfg.get("interval_seconds", 600) or 600), 60.0)
self.plugin_manager.start_hot_reload_watcher(interval_seconds=interval_seconds)
self.LOG.info(f"插件热加载监听已启用,轮询间隔 {interval_seconds}s")
else:
self.LOG.info("插件热加载监听已禁用,启动阶段不再自动扫盘检查插件变更")
self.system_job_loader = SystemJobLoader(self, self.system_job_db)
self.system_job_loader.init_and_load()
self.plugin_schedule_manager = PluginScheduleManager(self.plugin_manager, self.plugin_schedule_db)