文章目录


在这里插入图片描述

每日一句正能量

一条路走不通,那就换个方向,一次尝试失败了,那就奔赴下一场。
不把“此路不通”等于“我不行”,只是这条路暂时不适合。执念常常比失败本身更耗人。真正强大的人不是从不失败,而是失败后转身的速度很快。

导读

本文以一个中大型企业应用从 HarmonyOS 6.0 升级到 6.1 的真实工程方法为背景,系统讲解发布分层、指标基线、功能开关、异常止损、回滚决策、数据兼容与复盘机制。文中的指标数值为脱敏示例,读者应根据自身业务规模和历史基线调整。

前言:升级失败,通常不是“代码写错”这么简单

不少团队把系统版本升级理解为一次常规编译:修改 SDK、解决编译错误、跑一遍测试、提交应用市场。对于个人项目,这种方式偶尔可行;对于拥有登录、支付、消息、数据库、地图、音视频或多设备协同能力的企业级应用,这种做法风险极高。

HarmonyOS 6.0 升级到 6.1 时,真正困难的部分并不只是 API 变化,而是以下问题同时发生:

  1. 新系统能力与旧业务逻辑交织,问题不一定在测试环境复现;
  2. 第三方 SDK、网络网关、服务端配置和端侧版本可能形成复杂组合;
  3. 用户设备、区域、网络、账号状态、数据量不同,导致长尾问题集中在线上暴露;
  4. 应用市场的分阶段发布只能控制“谁收到新版本”,不能替代应用内部的功能开关与降级;
  5. 数据结构或协议一旦不可逆升级,即使客户端版本被替换,也未必能恢复旧链路。

因此,企业升级的目标不能只写成“6.1 版本成功上架”,而应定义为:

在可观测、可暂停、可降级、可修复的前提下,让新版本逐步接管流量,并确保任何阶段出现严重异常时都能迅速止损。

在这里插入图片描述


一、先拆清楚:灰度发布、功能灰度与版本回滚不是一回事

1. 商店分阶段发布

分阶段发布用于控制新版本的分发比例。团队可以先让少量用户获得 6.1 版本,再根据数据逐步扩大覆盖范围。

它解决的是:

  • 新安装或升级用户的版本覆盖比例;
  • 大规模发布前的风险探测;
  • 不同阶段的版本数据对比。

它不能直接解决:

  • 已升级用户的新功能关闭;
  • 服务端协议不兼容;
  • 本地数据已经完成不可逆迁移;
  • 某个业务模块单独回退;
  • 第三方服务异常时的客户端降级。

2. 应用内功能灰度

功能灰度是应用启动或进入业务页面时,从配置中心获取开关,根据用户、设备、地区、账号或实验桶决定是否启用新能力。

典型开关包括:

enable_new_home_61
enable_live_view_logistics
enable_new_payment_bridge
enable_database_schema_v4
enable_cross_device_sync

功能灰度的价值是:即使用户已经安装 6.1 版本,企业仍能远程关闭高风险功能,恢复旧实现。

3. 服务端灰度

客户端升级经常伴随接口字段、鉴权、缓存、推荐策略或订单状态机变化。服务端也要按客户端版本、灰度桶和用户标签进行兼容。

推荐在请求头中携带最少必要信息:

X-App-Version: 4.6.0
X-OS-Platform: HarmonyOS
X-OS-Api-Level: 6.1-compatible
X-Release-Channel: phased-20
X-Experiment-Bucket: B

服务端不得简单假设“所有用户都已经升级”,而应在较长时间内同时支持 6.0 与 6.1 客户端。

4. 版本回滚

版本回滚是最后一道防线,但不能被当作第一响应手段。因为:

  • 分阶段发布中的版本存在平台规则与适用条件;
  • 已安装的新版本不会因为团队停止扩量就自动恢复;
  • 本地数据库、缓存和用户数据可能已经迁移;
  • 回退审核、重新分发和用户安装都需要时间;
  • 紧急情况下,远程开关通常比发布新包更快。

所以企业必须建立多级止损体系:

一级:关闭单个功能开关
二级:切换服务端旧接口或静态兜底
三级:暂停灰度扩量
四级:停止版本发布并提交修复包
五级:满足平台条件时执行版本回退

二、升级前建立“6.0 稳定性基线”

没有基线,就无法判断 6.1 的指标变化究竟是异常,还是业务自然波动。

建议至少采集升级前连续 7~14 天的数据,并区分工作日、周末、促销日和普通日。

1. 技术稳定性指标

指标 推荐统计方式 示例基线 灰度警戒线
崩溃率 崩溃会话 / 总会话 0.16% 超过 0.30%
APP Freeze 率 卡死会话 / 总会话 0.08% 超过 0.15%
冷启动 P95 95 分位启动耗时 1.76 秒 上涨超过 15%
首屏可交互 P95 页面可交互耗时 2.10 秒 上涨超过 15%
内存峰值 P95 核心场景峰值 310 MB 上涨超过 20%
核心接口成功率 成功请求 / 总请求 99.72% 低于 99.50%
网络超时率 超时请求 / 总请求 0.21% 超过 0.50%

2. 业务指标

技术指标正常,不代表用户体验正常。升级必须同时观察:

  • 登录成功率;
  • 首页到达率;
  • 搜索成功率;
  • 下单转化率;
  • 支付成功率;
  • 消息点击率;
  • 订单详情打开率;
  • 用户投诉量;
  • 客服工单关键词;
  • 次日留存和七日留存。

例如,页面没有崩溃,但按钮点击区域错位,支付转化仍会明显下降。

3. 版本维度必须进入所有埋点

每条关键事件至少附带:

export interface ReleaseContext {
  appVersion: string
  osVersion: string
  deviceType: string
  releaseStage: string
  experimentBucket: string
  featureFlags: Record<string, boolean>
}

这样才能回答:

  • 异常是否只发生在 6.1 版本?
  • 是否只发生在某一类设备?
  • 是否只出现在新首页实验桶?
  • 是否与某个功能开关同时开启有关?
  • 是否为服务端全局故障?

三、企业级灰度分层:不要直接从 5% 跳到 100%

一个稳妥的升级流程可分为七个阶段。

阶段 0:发布前冻结

进入发布窗口前完成:

  • 冻结非必要需求;
  • 锁定依赖版本;
  • 完成全量回归;
  • 生成候选包哈希;
  • 归档配置、证书与构建日志;
  • 建立 6.0 基线;
  • 验证所有远程开关;
  • 演练服务端降级;
  • 演练紧急修复包流程。

阶段 1:内部验证

目标用户是研发、测试、产品、运营和核心员工。重点不是“再跑一次用例”,而是模拟真实账号和真实数据。

内部阶段至少覆盖:

  • 新用户注册;
  • 老用户升级;
  • 超大本地数据用户;
  • 多账号切换;
  • 弱网和断网;
  • 前后台切换;
  • 系统权限拒绝;
  • 通知关闭;
  • 跨设备场景;
  • 第三方支付和推送回调。

阶段 2:1% 探针

1% 阶段用于验证最基础的发布链路:

  • 应用能否正常下载和安装;
  • 是否出现启动崩溃;
  • 登录、首页、核心接口是否正常;
  • 监控数据是否准确进入平台;
  • 功能开关是否按用户生效;
  • 客服是否出现集中反馈。

建议观察 2~4 小时,但重大业务应覆盖一个完整高峰周期。

阶段 3:5% 小流量

5% 阶段开始覆盖更多机型、地区和用户画像。此时重点关注长尾问题和业务转化。

推荐将 5% 用户拆成两组:

  • 6.1 新版本 + 新功能关闭;
  • 6.1 新版本 + 新功能开启。

这样可以区分“系统升级问题”和“新功能问题”。

阶段 4:20% 扩量

20% 阶段已能暴露容量、缓存击穿、消息积压和第三方服务配额问题。

此阶段要增加:

  • 服务端资源水位;
  • 消息队列积压;
  • 数据库慢查询;
  • 第三方接口限流;
  • 推送 Token 更新率;
  • 支付回调延迟;
  • 日志上报带宽。

阶段 5:50% 主流量

50% 阶段意味着新版本进入主流量,任何小概率问题都会放大。此时不建议再合入无关改动。

放量条件应由发布委员会确认,而不是由单个开发人员判断。

阶段 6:100% 全量

全量不代表发布结束。至少继续观察 24~72 小时,并保留:

  • 新功能开关;
  • 服务端旧协议;
  • 监控告警;
  • 紧急修复分支;
  • 回滚决策人和值班表。

四、设计可执行的放量门禁

每一阶段必须有明确的“继续、暂停、回退”条件。

1. 继续放量

以下条件同时满足时才可扩量:

  • P0、P1 故障为零;
  • 崩溃率未超过阈值;
  • 冷启动和首屏耗时在容忍范围内;
  • 核心接口成功率无显著下降;
  • 登录、支付、下单等业务指标与对照组差异可接受;
  • 客服和舆情无集中问题;
  • 关键设备覆盖达到要求;
  • 已观察完整业务高峰。

2. 暂停扩量

满足任意一项即暂停:

  • 指标接近阈值但尚未确认原因;
  • 新版本与对照组差异持续扩大;
  • 某个地区或设备类型异常;
  • 日志上报缺失,无法准确判断;
  • 第三方服务出现间歇性故障;
  • 客服出现同类问题但尚未形成规模;
  • 服务端资源水位接近上限。

暂停不等于失败。暂停是灰度机制正常发挥作用。

3. 立即止损

满足任意一项应立即执行关闭开关、降级或停止发布:

  • 登录、支付、数据安全等核心链路不可用;
  • 出现数据丢失、重复扣款、订单错乱;
  • 崩溃率超过硬阈值;
  • APP Freeze 明显上升;
  • 新版本导致服务端雪崩;
  • 隐私权限或合规问题;
  • 用户无法通过常规操作恢复。

五、ArkTS 功能开关与发布上下文设计

1. 功能开关模型

export interface FeatureFlag {
  key: string
  enabled: boolean
  minVersion?: string
  maxVersion?: string
  rolloutPercent?: number
  allowUserIds?: string[]
  denyDeviceModels?: string[]
  expiresAt?: number
}

export interface FeatureSnapshot {
  version: string
  fetchedAt: number
  flags: Record<string, FeatureFlag>
}

2. 灰度桶计算

为了让同一用户长期落在同一实验桶,不能每次随机。

export class BucketUtil {
  static hash(value: string): number {
    let hash = 0
    for (let i = 0; i < value.length; i++) {
      hash = ((hash << 5) - hash) + value.charCodeAt(i)
      hash |= 0
    }
    return Math.abs(hash)
  }

  static hit(userId: string, key: string, percent: number): boolean {
    const bucket = BucketUtil.hash(`${userId}:${key}`) % 100
    return bucket < percent
  }
}

3. 开关判断

export class FeatureGate {
  constructor(private snapshot: FeatureSnapshot) {}

  isEnabled(
    key: string,
    userId: string,
    appVersion: string,
    deviceModel: string
  ): boolean {
    const flag = this.snapshot.flags[key]
    if (!flag || !flag.enabled) {
      return false
    }

    if (flag.allowUserIds?.includes(userId)) {
      return true
    }

    if (flag.denyDeviceModels?.includes(deviceModel)) {
      return false
    }

    if (flag.expiresAt && Date.now() > flag.expiresAt) {
      return false
    }

    const percent = flag.rolloutPercent ?? 100
    return BucketUtil.hit(userId, key, percent)
  }
}

4. 本地缓存与失败兜底

配置中心请求失败时,应用不能无限等待,也不能默认开启所有新功能。

推荐策略:

远程配置成功 → 使用最新快照
远程配置失败且本地快照未过期 → 使用缓存
远程配置失败且缓存过期 → 使用内置安全默认值

安全默认值应关闭高风险新能力。

const SAFE_DEFAULTS: Record<string, boolean> = {
  enable_new_home_61: false,
  enable_new_payment_bridge: false,
  enable_database_schema_v4: false,
  enable_live_view_logistics: false
}

六、监控 Dashboard 应该看什么

在这里插入图片描述

1. 第一屏:发布总览

应包含:

  • 当前灰度比例;
  • 6.1 活跃用户数;
  • 6.0 对照组用户数;
  • 最新版本安装成功率;
  • 灰度阶段开始时间;
  • 当前负责人;
  • 下一次评审时间;
  • 当前决策:继续、暂停或止损。

2. 第二屏:稳定性

包括:

  • 崩溃率趋势;
  • 崩溃 Top 堆栈;
  • APP Freeze;
  • PROCESS KILL;
  • 资源泄漏;
  • 启动耗时;
  • 页面加载耗时;
  • 内存与功耗;
  • 网络失败和超时。

AppGallery Connect 的应用性能监测能力可以帮助团队查看崩溃与性能问题,但企业仍应结合业务埋点、服务端指标和客服数据形成完整视图。

3. 第三屏:核心业务漏斗

例如电商应用:

启动成功
  ↓
登录成功
  ↓
首页到达
  ↓
商品详情
  ↓
提交订单
  ↓
支付成功

灰度判断不能只看最终支付率,还要看漏斗在哪一层开始下降。

4. 第四屏:分群诊断

按以下维度切分:

  • 版本;
  • 设备类型;
  • 设备型号;
  • 地区;
  • 网络类型;
  • 新老用户;
  • 数据量级;
  • 灰度桶;
  • 功能开关组合;
  • 安装方式;
  • 前后台状态。

七、异常回滚决策树

在这里插入图片描述

异常发生后,团队应先回答四个问题:

  1. 是否影响核心链路或数据安全?
  2. 是否只发生在 6.1 新版本?
  3. 是否与某个新功能开关强相关?
  4. 是否能通过远程配置或服务端降级迅速止损?

场景 A:新首页导致崩溃

处理顺序:

  1. 关闭 enable_new_home_61
  2. 强制进入旧首页;
  3. 暂停扩量;
  4. 分析崩溃堆栈;
  5. 修复后仅对内部和 1% 用户重新开启;
  6. 确认稳定后恢复原阶段。

这类问题无需立即回退整个应用版本。

场景 B:支付协议不兼容

处理顺序:

  1. 服务端按客户端版本切回旧支付协议;
  2. 关闭新支付桥接层;
  3. 对失败订单执行幂等核验;
  4. 暂停扩量;
  5. 检查是否存在重复扣款或订单状态不一致;
  6. 必要时发布紧急修复版本。

支付问题属于高风险场景,应优先保证资金与订单一致性。

场景 C:数据库迁移导致数据异常

如果新版本已经写入旧版本无法识别的数据,单纯安装旧版本可能无法恢复。

必须提前设计:

  • 升级前备份关键数据;
  • 迁移脚本幂等;
  • 数据库版本号;
  • 新旧字段并存窗口;
  • 服务端重新拉取能力;
  • 迁移失败标记;
  • 数据一致性校验。

场景 D:服务端全局故障

如果 6.0 与 6.1 同时异常,则不应误判为客户端升级问题。此时应按服务端故障处理,避免无意义地回退客户端。


八、服务端降级:真正快速的“软回滚”

客户端版本变化慢,服务端开关变化快。企业应把高风险能力设计为可降级。

1. 接口协议双版本

/api/v1/order/detail  ← 旧协议
/api/v2/order/detail  ← 新协议

或者保持同一路径,通过版本头处理。

新协议上线后,旧协议至少保留一个完整版本周期。

2. 响应字段向后兼容

新增字段应提供默认值,避免旧客户端解析失败。

{
  "orderId": "A10001",
  "status": "DELIVERING",
  "liveView": {
    "enabled": false,
    "templateId": ""
  }
}

旧客户端忽略 liveView,新客户端按开关使用。

3. 静态兜底

推荐、地图、活动页等非核心能力异常时,可返回:

  • 默认列表;
  • 缓存数据;
  • 简化页面;
  • H5 兜底;
  • “稍后重试”状态。

降级页面必须经过设计和测试,不能临时拼凑。


九、数据库与本地状态的回滚兼容

系统升级常伴随 Schema 变更。灰度阶段必须考虑新旧版本并存。

1. 扩展优先,不急于删除

例如 6.1 新增 sync_state

ALTER TABLE orders ADD COLUMN sync_state INTEGER NOT NULL DEFAULT 0;

不要在同一版本立刻删除旧字段。更稳妥的顺序是:

版本 A:新增字段,旧字段继续读写
版本 B:双写并校验
版本 C:只读新字段,保留旧字段
版本 D:确认无旧版本后再考虑清理

2. 迁移脚本必须幂等

迁移过程中应用可能被杀死、重启或重复执行。

async function migrateToV4(store: relationalStore.RdbStore): Promise<void> {
  await store.beginTransaction()
  try {
    // 伪代码:先检查字段或迁移标记,再执行变更
    await ensureColumnExists(store, 'orders', 'sync_state')
    await backfillSyncState(store)
    await writeMigrationMarker(store, 'v4_done')
    await store.commit()
  } catch (error) {
    await store.rollBack()
    throw error
  }
}

具体 API 应以项目使用的 HarmonyOS SDK 版本为准。

3. 数据校验

灰度阶段至少校验:

  • 行数;
  • 主键唯一性;
  • 非空字段;
  • 金额汇总;
  • 状态分布;
  • 本地与服务端关键字段一致性;
  • 失败迁移数量;
  • 迁移耗时。

十、发布自动化:让门禁进入流水线

人工表格容易漏项。建议将以下检查加入 CI/CD:

代码扫描
  ↓
单元测试
  ↓
UI 自动化
  ↓
兼容性测试
  ↓
性能基线比较
  ↓
隐私合规扫描
  ↓
构建签名
  ↓
产物哈希归档
  ↓
测试环境验证
  ↓
人工发布审批

示例:发布清单模型

export interface ReleaseChecklist {
  buildId: string
  versionName: string
  versionCode: number
  gitCommit: string
  artifactSha256: string
  unitTestPassed: boolean
  uiTestPassed: boolean
  performancePassed: boolean
  privacyPassed: boolean
  rollbackPlanReady: boolean
  onCallConfirmed: boolean
}

禁止“同包不同配置不可追溯”

发布时必须归档:

  • 构建参数;
  • 环境变量;
  • 远程配置版本;
  • 服务端接口版本;
  • 数据库 Schema;
  • 第三方 SDK 版本;
  • 签名证书;
  • 提交人和审批人;
  • 发布时间;
  • 灰度比例变更记录。

十一、组织机制:发布不是研发单兵作战

1. 发布角色

角色 主要职责
发布负责人 统一决策、控制节奏
客户端负责人 版本问题定位、功能开关
服务端负责人 接口兼容、降级、容量
测试负责人 回归与风险确认
数据负责人 Dashboard 与异常分析
运维/SRE 告警、资源与故障处置
产品负责人 业务影响判断
客服/运营 用户反馈与舆情
合规负责人 权限、隐私与上架风险

2. 发布群中必须固定播报

每次放量前后发送结构化信息:

【6.1 灰度播报】
当前阶段:5% → 20%
开始时间:14:00
观察窗口:4 小时
核心指标:崩溃率 0.18%,登录成功率 99.42%
异常情况:冷启动 P95 上涨 3.4%,未越阈值
当前开关:新首页开,新支付桥关闭
负责人:客户端 A / 服务端 B / 数据 C
下一决策点:18:00

十二、常见踩坑与解决方案

坑 1:只看总崩溃率

总崩溃率可能被大量稳定旧版本用户稀释。必须按版本、设备和灰度桶拆分。

坑 2:灰度用户每天变化

随机抽样导致用户今天开启、明天关闭,行为不可复现。应使用稳定哈希分桶。

坑 3:远程配置失败时默认开启

这是高风险错误。配置失败时应使用缓存或安全默认值。

坑 4:功能关闭但初始化仍执行

界面入口关闭了,SDK 或后台任务仍初始化,崩溃依旧发生。功能开关必须覆盖初始化、任务、入口和数据写入。

坑 5:只有客户端开关,没有服务端开关

客户端无法快速生效,服务端仍返回新协议。端云必须同时具备降级能力。

坑 6:数据库迁移不可逆

升级后删除旧字段,导致旧版本无法读取。应采用扩展、双写、验证、清理的多版本策略。

坑 7:监控上报本身失效

新版本网络层异常时,崩溃和业务埋点可能一起丢失。要结合服务端日志、应用市场反馈和客服工单交叉判断。

坑 8:只观察技术指标

按钮不可点击、文案遮挡、流程变长不会触发崩溃,但会影响转化。必须观察业务漏斗。

坑 9:未覆盖存量大数据用户

内部账号数据少,迁移很快;真实用户可能有数万条记录。测试需要构造大数据量。

坑 10:把“停止扩量”当成“完成回滚”

停止扩量只能保护尚未升级的用户,已升级用户仍需要功能关闭、服务端降级或修复版本。

坑 11:阈值写死,不参考基线

不同业务的正常崩溃率和成功率不同。阈值应结合历史数据、业务等级和样本量。

坑 12:样本太小就下结论

1% 灰度可能只有几十个核心事件。应同时设置最小用户数、最小事件量和观察时长。

坑 13:周末数据与工作日直接比较

业务波动会造成误判。最好使用同期对照组,而不是只与昨天比较。

坑 14:紧急修复包夹带新需求

修复包必须最小化变更,避免引入第二轮风险。

坑 15:全量后立即删除旧逻辑

仍有用户未升级。旧接口、旧字段和旧开关应保留合理窗口。


十三、适合校企合作项目的实训设计

作为校企合作讲师,我建议把本主题设计成一次“发布演练课”,而不是只讲概念。

实训任务

学生分为客户端、服务端、测试、数据和发布五个小组,完成:

  1. 为一个 HarmonyOS 6.1 示例应用增加新首页;
  2. 实现稳定哈希灰度;
  3. 建立 6.0 对照组;
  4. 设计 1%、5%、20%、50%、100% 发布流程;
  5. 制造一次新首页崩溃;
  6. 通过远程开关关闭新首页;
  7. 输出事件时间线;
  8. 提交故障复盘。

评分维度

  • 是否有清晰指标;
  • 是否能快速止损;
  • 是否保留旧链路;
  • 是否能定位版本与功能;
  • 是否有数据一致性校验;
  • 是否有责任人与决策记录;
  • 是否完成复盘和改进。

这类实训能帮助学生理解:企业开发不仅是实现功能,还包括发布、监控、稳定性和风险管理。


十四、上线检查清单

发布与构建

  • 版本号与构建号正确;
  • Git 提交已打 Tag;
  • 产物哈希已归档;
  • 依赖版本已锁定;
  • 证书与 Profile 正确;
  • 正式环境配置已复核;
  • 调试日志和测试入口已关闭;
  • 构建可重复;
  • 紧急修复分支已准备;
  • 发布审批已完成。

兼容与测试

  • 6.0 升级到 6.1 测试通过;
  • 新安装测试通过;
  • 老账号和新账号测试通过;
  • 大数据量迁移通过;
  • 弱网、断网测试通过;
  • 权限拒绝路径可用;
  • 前后台切换正常;
  • 多设备形态覆盖;
  • 第三方 SDK 回调正常;
  • 核心 UI 无遮挡和误触。

功能开关

  • 高风险能力均有开关;
  • 开关可远程生效;
  • 配置失败有安全默认值;
  • 用户分桶稳定;
  • 可按版本控制;
  • 可按设备控制;
  • 关闭入口同时停止初始化;
  • 开关操作有审计记录;
  • 开关过期时间已设置;
  • 已完成一次关闭演练。

监控与告警

  • 崩溃率看板就绪;
  • APP Freeze 看板就绪;
  • 启动耗时看板就绪;
  • 核心接口看板就绪;
  • 登录与支付看板就绪;
  • 版本维度可筛选;
  • 灰度桶可筛选;
  • 告警联系人正确;
  • P0/P1 告警已测试;
  • 客服反馈通道已建立。

回滚与降级

  • 服务端兼容旧协议;
  • 新接口可切回旧接口;
  • 静态兜底已验证;
  • 数据库迁移幂等;
  • 关键数据可恢复;
  • 停止扩量流程明确;
  • 紧急修复包流程明确;
  • 平台回退适用条件已确认;
  • 决策人和值班表明确;
  • 故障复盘模板已准备。

十五、总结

HarmonyOS 6.0 到 6.1 的企业级升级,不应被视为一次简单的 SDK 更新,而是一场涉及客户端、服务端、数据、测试、运维、产品和客服的协同发布。

一套真正可靠的升级体系,应具备以下特征:

  1. 有基线:知道旧版本正常状态是什么;
  2. 有分层:从内部、1%、5%、20%、50% 到全量逐步验证;
  3. 有对照:区分系统版本问题、新功能问题和全局服务问题;
  4. 有开关:已升级用户也能快速关闭高风险能力;
  5. 有降级:服务端和客户端都保留旧链路;
  6. 有监控:技术指标、业务指标与用户反馈共同判断;
  7. 有止损:先软回滚,再暂停扩量,最后考虑版本级处置;
  8. 有复盘:把每一次异常转化为下一次发布的自动化门禁。

灰度发布的价值,不是证明新版本“绝对没有问题”,而是用最小的用户影响发现问题,并让团队在风险扩大之前拥有足够多的选择。


转载自:https://blog.csdn.net/u014727709/article/details/162995022
欢迎 👍点赞✍评论⭐收藏,欢迎指正

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐