将推送系统平滑过渡到HarmonyOS 5 HMS Push的实践

110 阅读3分钟

以下为 ​​从第三方推送系统平滑迁移到HarmonyOS 5 HMS Push的完整实践方案​​,包含双通道并行、数据迁移和灰度发布的代码实现:


1. 迁移架构设计

image.png


2. 双通道并行模式

2.1 推送路由决策

// push-router.ets
import { HMSPush, LegacyPush } from '@ohos.push';

class PushRouter {
  private static readonly MIGRATION_PHASE = 'gradual'; // gradual | complete

  static async send(push: PushMessage): Promise<void> {
    if (this.MIGRATION_PHASE === 'complete') {
      return HMSPush.send(push);
    }

    // 双通道并行发送
    await Promise.allSettled([
      HMSPush.send(push),
      LegacyPush.send(push)
    ]);
  }

  static setPhase(phase: 'gradual' | 'complete'): void {
    this.MIGRATION_PHASE = phase;
  }
}

2.2 消息去重处理

// deduplicator.ets
class PushDeduplicator {
  private static receivedIds = new Set<string>();

  static async handle(push: PushMessage): Promise<boolean> {
    if (this.receivedIds.has(push.msgId)) {
      return false;
    }

    this.receivedIds.add(push.msgId);
    return true;
  }

  static cleanExpired(): void {
    const now = Date.now();
    this.receivedIds.forEach(id => {
      if (id.timestamp < now - 7 * 24 * 3600 * 1000) {
        this.receivedIds.delete(id);
      }
    });
  }
}

3. HMS Push集成

3.1 初始化配置

// hms-init.ets
import hms from '@ohos.hms.push';

class HMSPushService {
  static async init(): Promise<void> {
    await hms.init({
      appId: 'your_hms_app_id',
      apiKey: 'your_api_key'
    });

    // 注册消息回调
    hms.onMessageReceived(msg => {
      PushHandler.process(msg);
    });

    // 获取推送token
    const token = await hms.getToken();
    await this._registerToken(token);
  }

  private static async _registerToken(token: string): Promise<void> {
    await UserService.updatePushToken({
      hmsToken: token,
      platform: 'harmony'
    });
  }
}

3.2 消息格式转换

// message-converter.ets
class MessageConverter {
  static toHMSFormat(legacyMsg: LegacyPushMessage): HMSPushMessage {
    return {
      notification: {
        title: legacyMsg.title,
        body: legacyMsg.content,
        click_action: legacyMsg.deepLink
      },
      data: {
        ...legacyMsg.customData,
        source: 'migration'
      }
    };
  }
}

4. 数据迁移方案

4.1 用户标签迁移

// tag-migrator.ets
class TagMigrator {
  static async migrate(userId: string): Promise<void> {
    const legacyTags = await LegacyPush.getUserTags(userId);
    await hms.push.setTags({
      userId,
      tags: this._convertTags(legacyTags)
    });
  }

  private static _convertTags(tags: LegacyTag[]): HMSTag[] {
    return tags.map(tag => ({
      key: `migrated_${tag.key}`,
      value: tag.value
    }));
  }
}

4.2 设备分组迁移

// group-migrator.ets
class GroupMigrator {
  static async migrate(groupId: string): Promise<void> {
    const devices = await LegacyPush.getGroupDevices(groupId);
    await hms.push.createTopicGroup({
      groupId: `migrated_${groupId}`,
      devices
    });
  }
}

5. 灰度发布策略

5.1 设备分组策略

// canary-strategy.ets
class CanaryRelease {
  private static readonly CANARY_RATIO = 0.2; // 20%灰度

  static shouldUseHMS(deviceId: string): boolean {
    const hash = this._hashDeviceId(deviceId);
    return hash < this.CANARY_RATIO;
  }

  private static _hashDeviceId(id: string): number {
    return parseInt(crypto.createHash('md5').update(id).digest('hex').slice(0, 8), 16) / 0xFFFFFFFF;
  }
}

5.2 渐进式迁移控制

// migration-controller.ets
class MigrationController {
  private static phases: MigrationPhase[] = [
    { name: 'phase1', ratio: 0.1, duration: 3 },
    { name: 'phase2', ratio: 0.5, duration: 7 },
    { name: 'phase3', ratio: 1.0, duration: 0 }
  ];

  static getCurrentPhase(): MigrationPhase {
    const now = new Date();
    return this.phases.find(p => 
      p.startDate <= now && (p.endDate ? p.endDate >= now : true)
    ) || this.phases[0];
  }

  static isInCanary(deviceId: string): boolean {
    const phase = this.getCurrentPhase();
    return CanaryRelease.shouldUseHMS(deviceId) && 
           CanaryRelease._hashDeviceId(deviceId) <= phase.ratio;
  }
}

6. 统一消息处理

6.1 消息处理器

// push-handler.ets
class UnifiedPushHandler {
  static async process(push: PushMessage): Promise<void> {
    if (!PushDeduplicator.handle(push)) return;

    switch (push.type) {
      case 'notification':
        await this._showNotification(push);
        break;
      case 'data':
        await this._processDataMessage(push);
        break;
    }

    Analytics.trackPushDelivery(push);
  }

  private static async _showNotification(push: PushNotification): Promise<void> {
    await NotificationManager.show({
      id: push.msgId,
      title: push.title,
      content: push.body
    });
  }
}

6.2 回退机制

// fallback-handler.ets
class PushFallback {
  static async handleHMSError(error: PushError): Promise<void> {
    if (error.code === 'SERVICE_UNAVAILABLE') {
      await LegacyPush.send(error.originalMessage);
    }
    ErrorReporter.track(error);
  }
}

7. 完整迁移示例

7.1 应用初始化

// app-entry.ets
async function onApplicationCreate(): Promise<void> {
  // 初始化双推送通道
  await Promise.all([
    HMSPushService.init(),
    LegacyPushService.init()
  ]);

  // 启动迁移监听
  MigrationWatcher.start();
}

7.2 消息发送流程

// notification-sender.ets
async function sendMarketingPush(campaign: Campaign): Promise<void> {
  const message = createPushMessage(campaign);
  
  try {
    await PushRouter.send(message);
  } catch (error) {
    await PushFallback.handleHMSError(error);
  }
}

8. 监控与指标

8.1 迁移监控面板

// migration-monitor.ets
@Component
struct MigrationDashboard {
  @State hmsSuccessRate: number = 0;
  @State legacyVolume: number = 0;

  build() {
    Column() {
      Gauge(title: "HMS成功率", value: this.hmsSuccessRate)
      Gauge(title: "旧系统流量", value: this.legacyVolume)
    }
    .onAppear(() => this._loadData())
  }

  private async _loadData(): Promise<void> {
    const [hms, legacy] = await Promise.all([
      Analytics.getHMSSuccessRate(),
      Analytics.getLegacyVolume()
    ]);
    this.hmsSuccessRate = hms;
    this.legacyVolume = legacy;
  }
}

8.2 关键性能指标

指标目标阈值监控频率
HMS送达率≥99.5%5分钟
双通道一致性≥99.9%实时
迁移完成度每日增长5%每日
回退率<0.1%每小时

9. 生产环境配置

9.1 双通道开关配置

// push-config.json
{
  "migration": {
    "phases": [
      {
        "name": "initial",
        "hmsWeight": 0.1,
        "fallback": true
      },
      {
        "name": "stable",
        "hmsWeight": 0.8,
        "fallback": false
      }
    ]
  }
}

9.2 证书与密钥管理

// cert-manager.ets
class PushCertManager {
  static async rotateKeys(): Promise<void> {
    const newKey = await HMSCore.generateNewKey();
    await SecureStorage.set('hms_push_key', newKey);
    await this._revokeOldKey();
  }

  private static async _revokeOldKey(): Promise<void> {
    const oldKey = await SecureStorage.get('hms_push_key_old');
    if (oldKey) {
      await HMSCore.revokeKey(oldKey);
    }
  }
}

10. 迁移完成验证

10.1 完整性检查

// integrity-checker.ets
class MigrationVerifier {
  static async verifyCompletion(): Promise<boolean> {
    const [hmsCount, legacyCount] = await Promise.all([
      Analytics.getHMSPushCount(),
      Analytics.getLegacyPushCount()
    ]);
    
    return hmsCount > legacyCount * 10; // HMS消息量需10倍于旧系统
  }
}

10.2 旧系统下线

// legacy-cleanup.ets
class LegacySystemCleanup {
  static async shutdown(): Promise<void> {
    await Promise.all([
      UserTagDB.archive(),
      PushTokenDB.exportToColdStorage(),
      LegacyPushAPI.disable()
    ]);
    
    ConfigManager.set('push.migration.complete', true);
  }
}

通过本方案可实现:

  1. ​零感知​​ 用户过渡体验
  2. ​99.9%​​ 消息一致性保障
  3. ​分钟级​​ 回退能力
  4. ​可视化​​ 迁移进度监控