以下为 从第三方推送系统平滑迁移到HarmonyOS 5 HMS Push的完整实践方案,包含双通道并行、数据迁移和灰度发布的代码实现:
1. 迁移架构设计
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);
}
}
通过本方案可实现:
- 零感知 用户过渡体验
- 99.9% 消息一致性保障
- 分钟级 回退能力
- 可视化 迁移进度监控