尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Strapi 数据迁移实战:深入解析 Remote Strapi Source Provider 的拉取机制与配置

Strapi 数据迁移实战:深入解析 Remote Strapi Source Provider 的拉取机制与配置 Strapi 数据迁移实战深入解析 Remote Strapi Source Provider 的拉取机制与配置【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapiStrapi 的 Remote Strapi Source Provider 是数据迁移data transfer体系中负责拉取pull方向的核心组件它通过 WebSocket 连接到远端 Strapi 实例按协议化步骤把 schema、实体、资产和配置数据完整搬到本地。本文基于 官方文档 与>// 远端实例 config/admin.js module.exports { transfer: { token: { salt: base64 随机字符串, }, }, };而禁用远端迁移的开关则在 远端总览文档 中给出// in config/server.js { transfer: { remote: { enabled: false; } } // ...the rest of your server config }二、Provider 选项url、auth 与 retryMessageOptions2.1 官方文档中的接口定义Source 文档 给出了远程 Provider 的选项接口interface ITransferTokenAuth { type: token; token: string; } export interface IRemoteStrapiDestinationProviderOptions extends PickILocalStrapiDestinationProviderOptions, restore | strategy { url: URL; auth?: ITransferTokenAuth; retryMessageOptions?: { retryMessageTimeout: number; // milliseconds to wait for a response from a message retryMessageMaxRetries: number; // max number of retries for a message before aborting transfer }; }文档同时强调url必须包含http或https协议前缀Provider 会将其转换为ws或wss来建立连接由于 transfer token 拥有很高的访问权限强烈建议使用加密连接https。2.2 源码中的完整接口与额外选项当前源码中IRemoteStrapiSourceProviderOptions继承自ILocalStrapiSourceProviderOptions并在文档列出的三个选项之外还增加了两个 source 侧专用选项见 remote-source/index.ts#L42-L53export interface IRemoteStrapiSourceProviderOptions extends ILocalStrapiSourceProviderOptions { url: URL; // the url of the remote Strapi admin auth?: Auth.ITransferTokenAuth; retryMessageOptions?: { retryMessageTimeout: number; // milliseconds to wait for a response from a message retryMessageMaxRetries: number; // max number of retries for a message before aborting transfer }; /** Max ms without forward progress on an asset (new remote chunk accepted or chunk fully handed to the asset stream). */ streamTimeout?: number; /** Require per-asset checksum verification for transferred asset bytes. */ verifyChecksums?: boolean; }逐项解读url: URL远端 Strapi 管理端地址必须是URL对象Node.js 中new URL(https://strapi.example.com)。Provider 会校验协议只允许https:/http:assertValidProtocol见 index.ts#L466-L478并在此基础上拼出 WebSocket 地址wss://hostpath/transfer/runner/pull。路径常量TRANSFER_PATH /transfer/runner定义在 remote/constants.ts路径末尾的斜杠会被trimTrailingSlash去掉因此url带不带尾斜杠都可以。auth?: ITransferTokenAuth认证方式为{ type: token, token: string }。bootstrap()中会把 token 组装为 HTTP 头Authorization: Bearer token传给 WebSocket 握手见 index.ts#L541-L549。该 token 由远端transfer.token.salt派生权限很高务必通过安全渠道传递。retryMessageOptions控制消息级重试两个字段含义见下文消息超时与重试一节。streamTimeout?: number单个资产asset在没有前进状态下的最大毫秒数——即长时间收不到新的远端 chunk、或 chunk 一直无法写入本地资产流时判定该资产卡死并中止。默认值在defaultOptions中为3000005 分钟index.ts#L69-L72。源码注释解释了默认值偏大的原因大文件配合 JSON/WebSocket 背压时相邻两条消息之间可能间隔数分钟但字节仍在本地持续消费过小的超时会误杀正常传输。verifyChecksums?: boolean要求对传输的每个资产做逐字节 SHA-256 校验。开启后init命令会附带params: { transfer: pull, checksums: true }请求协商见 index.ts#L480-L502若远端不支持协商则降级为不校验并输出警告若远端支持则校验失败会抛出ProviderTransferError如 Checksum mismatch for asset ...。2.3 CLI 中的实际装配在strapi transfer命令中remote source provider 是这样被创建的见 transfer 命令动作source createRemoteStrapiSourceProvider({ getStrapi: () strapi, url: opts.from, auth: { type: token, token: opts.fromToken, }, ...(assetIdleTimeoutMs ! undefined ? { streamTimeout: assetIdleTimeoutMs } : {}), ...(checksumsEnabled ? { verifyChecksums: true } : {}), });可以推断当命令带有--from url与--from-token token参数时CLI 就走这条拉取链路streamTimeout来自服务端配置server.transfer.remote.assetIdleTimeoutMs经resolveRemotePullAssetIdleTimeoutMs校验为正的有限数字才生效而verifyChecksums的 CLI 侧默认是开启的checksumsEnabled opts.checksums ! false。三、连接建立协议转换、路由与认证错误映射bootstrap()是 remote source provider 的入口完整链路为校验协议 → 建立 WebSocket → 创建 dispatcher → init 拿 transferID → 发送bootstrap动作见 index.ts#L527-L577this.assertValidProtocol(url); const wsProtocol url.protocol https: ? wss: : ws:; const wsUrl ${wsProtocol}//${url.host}${trimTrailingSlash(url.pathname)}${TRANSFER_PATH}/pull; if (!auth) { ws await connectToWebsocket(wsUrl, undefined, this.#diagnostics); } else if (auth.type token) { const headers { Authorization: Bearer ${auth.token} }; ws await connectToWebsocket(wsUrl, { headers }, this.#diagnostics); } // ... this.dispatcher createDispatcher(this.ws, retryMessageOptions, (message) this.#reportInfo(message)); const transferID await this.initTransfer(); this.dispatcher.setTransferProperties({ id: transferID, kind: pull }); await this.dispatcher.dispatchTransferAction(bootstrap);几个要点协议转换是自动的你只需在url中写https://...或http://...源码负责映射为wss:/ws:这与文档中will then be converted towssorws的说法一致。路由固定为/pull远端实例只暴露pull与push两条迁移路由/admin/transfer/runner/pull与/admin/transfer/runner/push见 WebSocket 文档 的连接阶段说明source provider 只连pulldestination provider 才连push。认证错误的精确映射connectToWebsocket 会捕获握手阶段的 HTTP 响应把常见状态码翻译成可直接排错的初始化错误401→ Authentication Errortoken 无效或过期403→ Authorization Error404→ Data transfer is not enabled on the remote host远端未配置 token salt 或server.transfer.remote.enabled为 false因此拉取失败时先看错误文案判断是token 问题还是远端未开启迁移功能能大幅缩短排错时间。init 命令与 transferIDinitTransfer()发送dispatchCommand({ command: init })服务端返回transferID之后所有消息都必须携带该 IDsetTransferProperties({ id: transferID, kind: pull })会把它注入后续 transfer 消息。init同时承担 checksum 协商请求校验时只有远端响应checksums: true才会真正启用校验。四、消息调度器dispatcher 与超时/重试机制remote provider 的所有交互都经由一个消息调度器完成。Websocket 文档 将 dispatcher 拆成三个方法dispatchCommand用于开关一次迁移的命令取值为init初始化返回 transferID与end结束连接dispatchTransferStep用于切换迁移阶段与流式数据action取start/stream可多条/end每条消息带step名称dispatchTransferAction触发与本地 Provider 等价的动作包括bootstrap、getMetadata、beforeTransfer、getSchemas、rollback仅 destination、close。其源码实现是 createDispatcher工作机制值得展开uuid 配对响应每条出站消息生成随机uuid响应监听器只在response.uuid uuid时解析结果不匹配的消息会挂回ws.once(message, ...)继续等待——这保证了乱序到达的响应也能被正确路由。周期性重发发送后启动setInterval(sendPeriodically, retryMessageTimeout)每次重发同一份序列化载荷直到收到匹配响应clearInterval重发次数超过retryMessageMaxRetries后抛出ProviderError(error, Request timed out)。默认值createDispatcher的默认参数为retryMessageMaxRetries: 5、retryMessageTimeout: 3000030 秒见 utils.ts#L35-L38。也就是说若你不提供retryMessageOptions单条消息最多等待约 30 秒×6 次首发5 次重发就会以超时中止。错误分类服务端返回的error会按step字段转成不同错误类型——transfer→ProviderTransferErrorvalidation→ProviderValidationErrorinitialization→ProviderInitializationError方便上层如 CLI按类别处理。4.1 assets 阶段的特殊重试窗口entities、links、configuration阶段用默认重试即可但assets阶段的start消息有一个专门的覆盖配置见 index.ts#L32-L40const ASSETS_START_RETRY_OVERRIDES: PartialRetryMessageOptions { retryMessageTimeout: 120_000, // 120 秒 retryMessageMaxRetries: 30, };原因在源码注释中写得很清楚pull 服务端只有在完成estimateAssetTotals数据库流式统计大库可能要几分钟之后才会回复assets阶段的start默认的 30 秒窗口会导致大资产库误报Request timed out。#startStep()在step assets时把该配置通过retryOverrides合并进本次消息的重试参数合并逻辑见 utils.ts#L80-L96覆盖值优先于 dispatcher 默认值。4.2 资产流式拉取的背压与卡死检测createAssetsReadStream()是 source provider 中最重的实现index.ts#L168-L454几个工程细节对理解大文件拉取很有价值单资产串行处理Readable.on(data)本身不做背压因此代码把载荷管道接进一个highWaterMark: 1的Writable保证同一时刻只有一个批次在途每资产独立队列与流start消息为资产创建PassThrough流和动作队列stream/end消息入队后由processQueue串行消费end时关闭该资产的流卡死检测每个资产都挂一个streamTimeout定时器收到新 chunk 或完成一次本地写入都会重置resetTimeout超时则报告 Asset xxx transfer stalled, aborting. 并销毁该资产流。慢排空也算前进因此慢而稳的大文件不会触发该定时器校验开启verifyChecksums时每个 chunk 都会先喂给createHash(sha256)end时与远端下发的 checksum 比对不匹配即抛错。五、完整迁移生命周期pull 视角结合 Websocket 文档 的状态机与时序说明一次完整的 pull 迁移按如下顺序进行连接阶段以Authorization: Bearer transfer_token头打开wss://host/admin/transfer/runner/pull初始化阶段dispatchCommand(init)换取transferID此后所有消息携带该 ID动作阶段依次bootstrap→getMetadata→beforeTransfer→getSchemasschemas 用于源/目标间的校验步骤阶段对每个 stageschemas、entities、assets、links、configuration执行start→ 若干stream→end每条消息受retryMessageTimeout/retryMessageMaxRetries保护超时自动重发超过上限则中止迁移收尾阶段dispatchTransferAction(close)完成迁移但不关闭连接→dispatchCommand({ command: end })→ 移除事件监听并关闭 WebSocket。source 侧的close()方法实现了其中的前半部分先派发close动作再等待ws的close事件后关闭连接见 index.ts#L579-L592。六、实践建议与适用前提安全transfer token 由远端transfer.token.salt派生且权限极高url务必使用https自动升级为wss加密通道不配置auth时 Provider 会尝试匿名公共访问这只应出现在明确开放匿名迁移的测试环境。超时调优小数据量迁移用默认值30s × 5 次重发即可如果远端资产库很大、estimateAssetTotals耗时长assets 阶段已有内置 120s × 30 次的宽松窗口一般无需干预如果你观察到大文件在弱网下被streamTimeout误判卡死可通过选项调大streamTimeout默认 5 分钟或在 CLI 场景通过远端配置server.transfer.remote.assetIdleTimeoutMs调整。完整性跨公网拉取时建议保留verifyChecksumsCLI 默认开启以字节级校验拦截传输错误。服务端前置条件远端必须配置admin.transfer.token.salt且server.transfer.remote.enabled不为false否则握手会得到 404 并提示 Data transfer is not enabled on the remote host。以上机制均基于当前仓库源码与文档验证接口定义见 remote-source/index.ts调度器实现见 providers/utils.ts路由常量见 strapi/remote/constants.tsCLI 装配见 transfer 命令协议细节可继续参考 Websocket 协议文档 与 Source 文档。【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表