文档目录
站点安装报告与数据分析系统

引言

本文件聚焦于 DouPHP 的「站点安装报告与数据分析系统」,即站点在安装、升级模块/主题/插件/小程序以及系统内核时,如何采集匿名基础遥测并上报到云端,用于统计安装/升级事件与站点环境快照。该系统以「零 admin 依赖、尽力而为、绝不阻断安装流程」为设计原则,通过 SiteReportService 统一封装采集与上报逻辑,由后台安装流程在收尾阶段触发上报。

最新更新:系统已增强大文件下载性能、模块配置写入并发安全、OPcache失效处理,以及新增邮件模块升级机制和会话超时延长至60分钟。

项目结构

DouPHP 采用「三端入口 + 共享核心 + 模块化」架构:前台 front、后台 admin、API api 各自独立入口,共享 core 核心层;业务按模块组织,配置集中于 config,运行时状态与缓存位于 storage。安装与升级相关的数据上报能力属于 core 层的云服务能力,被 admin 端的安装服务调用。

graph TB
A["前台入口<br/>index.php"] --> B["核心引导<br/>core/bootstrap.php"]
C["后台入口<br/>admin/index.php"] --> D["后台控制器<br/>CloudController"]
D --> E["安装服务<br/>InstallService"]
E --> F["站点上报服务<br/>SiteReportService"]
F --> G["云端 API<br/>CloudApi::postJson"]
H["存储目录<br/>storage/install/*"] -.-> E
I["配置中心<br/>Config / cloud.php"] -.-> F
J["会话服务<br/>InstallSessionService"] -.-> E
K["邮件模块升级<br/>email/_update"] -.-> E

核心组件

  • 安装流程编排者:后台安装服务负责多步安装(预检、下载、解压、应用、收尾),并在收尾阶段触发上报。
  • 站点上报服务:封装站点环境快照采集、开关判断、云端地址校验、异常吞掉等逻辑,保证上报失败不影响安装。
  • 安装会话服务:管理安装会话的生命周期,提供60分钟超时支持和并发安全的文件锁机制。
  • 前端入口与异常处理:前台入口负责路由分发与全局异常渲染,确保 JSON 请求返回结构化错误,HTML 请求走提示页或调试页。

新增功能:

  • 大文件流式下载:支持~10M系统升级包的高效下载
  • 并发安全的配置写入:使用文件锁和OPcache失效处理
  • 邮件模块升级:支持email模块的数据迁移和版本升级

架构总览

下图展示从后台安装流程到云端上报的端到端时序,包含新增的大文件下载和会话管理机制。

sequenceDiagram
participant Admin as "后台控制器"
participant Install as "安装服务 InstallService"
participant Session as "会话服务 InstallSessionService"
participant Report as "站点上报服务 SiteReportService"
participant Cloud as "云端接口 CloudApi"
Admin->>Install : "runPreflight(type, cloud_id, mode, version)"
Install->>Session : "create(params)"
Session-->>Install : "install_id"
Admin->>Install : "runDownload(download_url)"
Install->>Install : "downloadFile() 流式下载"
Install->>Install : "attemptStreamDownload()"
Install->>Install : "完整性校验 + 重试机制"
Admin->>Install : "runUnzip()"
Admin->>Install : "runApply()"
Install->>Install : "changeModulePhp() 并发安全写入"
Install->>Install : "OPcache失效处理"
Admin->>Install : "runFinalize()"
Install->>Report : "reportSystem() 或 reportExtend()"
Report->>Report : "ensureCloudConfig()"
Report->>Report : "collectSite()"
Report->>Cloud : "POST /report/site"
Cloud-->>Report : "HTTP 响应"
Report-->>Install : "void静默"
Install-->>Admin : "返回结果包含 next_install"

详细组件分析

安装服务中的上报触发点

  • 触发时机:安装收尾阶段 runFinalize,在写入审计日志之后、构建成功按钮之前。
  • 触发条件:
    • 系统升级:调用 reportSystem(eventType, toVersion, fromVersion),其中 fromVersion 来自 runApply 阶段暂存到 Session 的值。
    • 扩展安装/升级(module/theme/plugin/miniprogram):调用 reportExtend(targetType, slug, eventType, toVersion)。
  • 容错策略:对上报调用整体 try/catch,捕获 Exception 与 Throwable,确保任何异常都不会阻断收尾流程。
flowchart TD
Start(["进入 runFinalize"]) --> Audit["记录审计日志"]
Audit --> TryReport{"是否可上报?"}
TryReport --> |是| CallReport["调用 SiteReportService"]
TryReport --> |否| BuildButtons["构建成功按钮"]
CallReport --> CatchErr{"是否发生异常?"}
CatchErr --> |是| Ignore["静默忽略"]
CatchErr --> |否| BuildButtons
Ignore --> BuildButtons
BuildButtons --> Next["计算下一个待安装项"]
Next --> End(["返回结果"])

大文件下载性能优化

新增功能:针对~10M系统升级包的性能优化,采用流式下载替代内存加载。

关键改进:

  • 流式下载:使用 Client::request() 的 stream_to 参数直接落盘,避免整包读入内存
  • 完整性校验:ZIP归档签名判定 + Content-Length比对 + ZipArchive结构验证
  • 智能重试:对瞬时网络错误、截断包、空响应等场景自动重试最多3次
  • 错误分类:区分上游不可用、权限不足、包损坏等不同错误类型
flowchart TD
Start(["downloadFile()"]) --> Clean["清理旧包文件"]
Clean --> Attempt["尝试流式下载"]
Attempt --> CheckCode{"HTTP状态码检查"}
CheckCode --> |非2xx| Classify["分类错误类型"]
CheckCode --> |2xx| Validate["ZIP完整性验证"]
Validate --> Signature["文件头签名检查"]
Signature --> Length["Content-Length比对"]
Length --> Structure["ZipArchive结构验证"]
Structure --> Success{"验证通过?"}
Success --> |是| Return["返回文件路径"]
Success --> |否| Retry["判断是否可重试"]
Retry --> |是| Backoff["退避等待后重试"]
Retry --> |否| Fail["返回失败"]
Classify --> Retry
Backoff --> Attempt

模块配置写入并发安全

新增功能:实现config/module.php文件的并发安全写入和OPcache失效处理。

关键特性:

  • 文件锁保护:使用 file_put_contents() 的 LOCK_EX 标志防止并发写冲突
  • OPcache失效:写盘成功后调用 opcache_invalidate() 确保下一请求重新编译
  • 原子性操作:先完整构建输出数组,再一次性写盘,避免部分写入
  • 键序保持:按原文件键序回写,保持配置文件结构一致性
flowchart TD
Start(["changeModulePhp()"]) --> Read["读取原始账本数据"]
Read --> Modify["修改模块标识和开关"]
Modify --> Build["构建输出数组"]
Build --> Write["file_put_contents(LOCK_EX)"]
Write --> Invalidate{"OPcache可用?"}
Invalidate --> |是| Inval["opcache_invalidate()"]
Invalidate --> |否| Skip["跳过失效处理"]
Inval --> Success["返回true"]
Skip --> Success

安装会话服务与会话超时

新增功能:安装会话服务支持60分钟超时,专为大体积系统升级包优化。

关键特性:

  • 60分钟TTL:TTL_SECONDS = 3600,适应共享主机上的长时间下载
  • 文件锁机制:使用 flock() 确保同一会话的并发请求串行化
  • 智能GC:构造时清理过期会话文件,避免目录无限增长
  • 健壮性设计:即使目录被删除也能重建,确保会话存续
classDiagram
class InstallSessionService {
+const SESSION_DIR = 'storage/install/session/'
+const TTL_SECONDS = 3600
+create(params) string
+load(installId) array|null
+save(installId, state) void
+delete(installId) void
+withLock(installId, fn) array|null
+pushLog(state, step, level, text) array
}

邮件模块升级机制

新增功能:新增email模块的升级机制,支持数据迁移和版本管理。

升级流程:

  • 版本检测:检查客户端版本是否满足最低要求
  • SQL升级:执行数据库结构变更和时间字段标准化
  • PHP升级:运行自定义升级逻辑
  • 缓存清理:升级完成后清理系统缓存
flowchart TD
Start(["email模块升级"]) --> CheckVersion["检查客户端版本"]
CheckVersion --> MinVersion{">= 20180703?"}
MinVersion --> |否| Skip["跳过升级"]
MinVersion --> |是| SQLUpgrade["执行SQL升级"]
SQLUpgrade --> PHPUpgrade["执行PHP升级"]
PHPUpgrade --> ClearCache["清理缓存"]
ClearCache --> End(["升级完成"])
Skip --> End

站点上报服务 SiteReportService

职责与行为:

  • 提供两类上报方法:
    • reportSystem(eventType, toVersion, fromVersion):核心版本安装/升级事件。
    • reportExtend(targetType, slug, eventType, toVersion, name):扩展(模块/主题/插件/小程序)安装/升级事件。
  • 唯一出口 send(event):
    • 按需加载 config/cloud.php,确保安装器上下文可用。
    • 检查开关 cloud.report_site 与 cloud.api_base,任一缺失则静默跳过。
    • 采集站点快照 collectSite(),合并事件字段后 POST 到 PATH_REPORT_SITE。
    • 所有异常与 PHP Error 均被吞掉,绝不影响安装/升级。
  • 站点快照字段:
    • domain、site_url、system_sign、cms_version、theme、language、php_version、mysql_version、server_software、os、cloud_account。
  • 域名解析:
    • 优先 ROOT_URL,回退 HTTP_HOST,去除端口并转小写。
  • MySQL 版本探测:
    • 若容器未绑定 Connection(如安装收尾请求),返回空串。
  • 云账号标识:
    • 仅读取 site.cloud_account.user,不携带 password。
classDiagram
class SiteReportService {
+reportSystem(eventType, toVersion, fromVersion) void
+reportExtend(targetType, slug, eventType, toVersion, name) void
-send(event) void
-ensureCloudConfig() void
-collectSite() array
-detectDomain() string
-detectMysqlVersion() string
-detectCloudAccount() string
}

前台入口与异常处理

前台入口负责:

  • 设置路由委托、语言前缀解析、Init 启动、路由分发。
  • 捕获业务异常、重定向异常、HTTP 响应异常,并按 JSON 或 HTML 输出。
  • 未捕获异常统一走 front_render_uncaught,根据 site.debug 输出调试页或通用错误。
flowchart TD
Entry["入口 index.php"] --> Boot["Init 启动"]
Boot --> Dispatch["路由分发"]
Dispatch --> Response{"是否 Response 对象?"}
Response --> |是| Send["发送响应并退出"]
Response --> |否| Continue["继续"]
Continue --> CatchHttp["捕获 HttpResponseException"]
CatchHttp --> CatchRedirect["捕获 RedirectException"]
CatchRedirect --> CatchDomain["捕获 DomainException"]
CatchDomain --> CatchGeneral["捕获 Exception/Throwable"]
CatchGeneral --> RenderUncaught["统一异常渲染"]

依赖关系分析

  • InstallService 依赖:
    • CacheClearService(清理模板缓存)、DB(表前缀与 SQL 执行)、Session(暂存旧版本)、Zip(解压)、FileHelper(文件操作)、RouteTableExporter/JsLangExporter(资源导出)、Client(网络请求)。
    • 最终通过 app() 解析 SiteReportService 实例并调用上报。
    • 新增:InstallSessionService(会话管理)、OpCache(缓存失效)。
  • SiteReportService 依赖:
    • Config(读取 cloud 配置)、CloudApi(POST 上报)、DB(可选探测 MySQL 版本)。
    • 使用 ROOT_PATH、ROOT_URL、SYSTEM_SIGN、PHP_VERSION、PHP_OS、$_SERVER 等运行期常量与环境变量。
graph LR
Install["InstallService"] --> App["app() 解析"]
App --> Report["SiteReportService"]
Install --> Session["InstallSessionService"]
Install --> OpCache["OPcache"]
Report --> Config["Config"]
Report --> CloudApi["CloudApi"]
Report --> DB["DB可选"]

性能与可靠性

  • 上报开销极低:仅在安装/升级收尾阶段触发一次,且开关关闭或未配置云端地址时直接跳过。
  • 安装器上下文自愈:若 Config 尚未 bootstrap,按需加载 config/cloud.php,避免额外依赖。
  • 异常吞掉:无论网络异常、配置异常、类解析异常,均不阻断安装流程。
  • 最小化敏感信息:仅采集匿名基础遥测,不包含密码,云账号只取 user。

新增性能优化:

  • 大文件下载优化:流式下载避免内存溢出,支持~10M系统升级包
  • 并发安全写入:文件锁保护config/module.php,防止并发写冲突
  • OPcache失效:配置变更后立即失效缓存,确保最新配置生效
  • 长会话支持:60分钟会话超时,适应长时间下载场景

故障排查指南

常见问题与定位建议:

  • 未收到上报:
    • 检查 cloud.report_site 是否为 true。
    • 检查 cloud.api_base 是否已配置。
    • 确认 config/cloud.php 是否存在并可读。
  • 上报失败但不影响安装:
    • 这是预期行为;查看后端日志与网络抓包,确认 CloudApi 是否可达。
  • 站点环境字段为空:
    • cms_version 可能为空(安装收尾阶段),但核心事件会用 to_version 填充。
    • mysql_version 在未绑定数据库连接时返回空串。
    • domain 解析失败时回退 HTTP_HOST,仍可能为空。
  • 云账号标识为空:
    • 检查 site.cloud_account 是否序列化正确且包含 user 字段。

新增问题排查:

  • 大文件下载失败:
    • 检查网络连接和服务器防火墙设置
    • 确认磁盘空间充足,支持临时文件创建
    • 查看错误分类:upstream_not_found、upstream_unavailable、truncated_package等
  • 模块配置写入失败:
    • 检查config/module.php文件权限
    • 确认OPcache函数可用:function_exists('opcache_invalidate')
    • 查看是否有其他进程同时写入该文件
  • 会话超时问题:
    • 检查storage/install/session目录权限
    • 确认TTL_SECONDS设置为3600秒(60分钟)
    • 查看是否有GC进程误删活跃会话
  • 邮件模块升级失败:
    • 检查数据库连接和权限
    • 确认最低版本要求:client_version_number > '20180703'
    • 查看升级日志和错误信息

结论

站点安装报告与数据分析系统以最小侵入的方式嵌入安装/升级收尾流程,通过统一的 SiteReportService 完成站点快照采集与云端上报。其设计强调"尽力而为"和"零阻塞",在保证安装稳定性的同时,为平台提供匿名基础遥测能力,便于统计安装/升级趋势与站点环境分布。

最新增强:系统现已具备强大的大文件处理能力、并发安全的配置管理、健壮的会话管理机制,以及完善的模块升级支持,能够高效处理~10M级别系统升级包,同时保证多进程环境下的数据一致性和用户体验。

附录:数据模型与字段说明

云端接收到的上报载荷包含站点快照与事件字段,关键字段如下:

  • 站点快照

    • domain:站点域名(host,去端口、小写)
    • site_url:站点根 URL
    • system_sign:系统签名
    • cms_version:CMS 版本(核心事件时可能用 to_version 填充)
    • theme:当前主题
    • language:当前语言
    • php_version:PHP 版本
    • mysql_version:MySQL 版本(不可用时为空)
    • server_software:服务器软件
    • os:操作系统
    • cloud_account:云账号标识(仅 user)
  • 事件字段

    • target_type:core / module / theme / plugin / miniprogram
    • target_slug:扩展标识(cloud_id),核心为空
    • target_name:扩展名称(可为空)
    • event_type:install / update / patch
    • to_version:目标版本
    • from_version:升级前版本(仅核心升级时有值)

新增数据模型:

  • 安装会话数据:
    • install_id:64位十六进制会话ID
    • created_at/updated_at:创建和更新时间戳
    • type/mode/version:安装类型、模式、版本
    • current_step/completed_steps:步骤进度跟踪
    • logs:安装过程日志数组
    • result:最终结果包含按钮HTML和下一个安装项
添加日期:2026-10-05