You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何快速向百万级设备发送FCM V1推送请求?

5分钟完成100万FCM V1推送的优化策略

一、HTTP/2客户端深度调优

  • 拉满HTTP/2并发流上限:FCM V1基于HTTP/2协议,单连接默认并发流数为100,可上调至FCM允许的最大值(建议设为1000,需结合实际测试验证)。同时优化IO线程数,匹配CPU核心数:
    this.httpClient = HttpAsyncClients.customHttp2()
            .setIOReactorConfig(IOReactorConfig.custom()
                    .setSoTimeout(Timeout.ofMinutes(1))
                    .setSelectInterval(Timeout.ofMilliseconds(100))
                    .setIoThreadCount(Runtime.getRuntime().availableProcessors() * 2)
                    .build())
            .setMaxConnPerRoute(1000)
            .setMaxConnTotal(1000)
            .build();
    
  • 预序列化固定Payload:将FCM请求中除token外的固定部分提前序列化为JSON字符串,每次发送仅替换token字段,避免重复序列化带来的CPU开销。

二、线程池与任务调度优化

  • 替换为弹性线程池:固定100线程的配置无法支撑每秒约3333次的请求量,改用自定义弹性线程池,避免任务堆积:
    threadPoolExecutor = new ThreadPoolExecutor(
            200, // 核心线程数
            1000, // 最大线程数
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<>(), // 同步队列,直接提交任务到线程
            new ThreadFactoryBuilder().setNameFormat("fcm-push-%d").build()
    );
    
  • 移除冗余Future包装:现有代码中用SettableFuture二次包装请求Future,增加不必要的开销,直接收集sender.send()返回的ListenableFuture即可:
    final List<ListenableFuture<Result>> futureList = new ArrayList<>();
    for (Recipient recipient : recipients) {
        futureList.add(sender.send(msg, recipient.getPushToken()));
    }
    // 用Futures.allAsList统一处理结果
    ListenableFuture<List<Result>> allResults = Futures.allAsList(futureList);
    

三、请求传输优化

  • 启用请求压缩:在HTTP请求头中添加Content-Encoding: gzip,将Payload压缩后发送,FCM支持gzip解码,可大幅减少网络传输时间。
  • 预创建HTTP请求实例:提前初始化HttpPost对象,仅在每次请求时更新请求体中的token字段,避免重复创建请求对象的开销。

四、错误处理与重试优化

  • 异步指数退避重试:针对FCM返回的可重试错误(503服务不可用、429请求超限),实现异步重试逻辑,用Futures.retryWhenFailed封装,避免同步阻塞浪费资源:
    ListenableFuture<Result> sendWithRetry(Message message, String token) {
        return Futures.retryWhenFailed(
                () -> sender.sendNoRetry(message, token),
                RetryPolicy.exponentialBackoff(3, 1000), // 最多重试3次,初始间隔1秒
                throwable -> {
                    // 判断是否为可重试错误
                    if (throwable instanceof FcmRetryableException) {
                        return true;
                    }
                    return false;
                },
                executorService
        );
    }
    
  • 批量处理错误结果:待所有请求完成后,统一统计失败的token列表,集中进行重试,减少单请求错误处理的分散开销。

五、系统与JVM调优

  • JVM参数优化:调整堆内存与垃圾收集策略,减少GC停顿:
    -Xmx8G -Xms4G -XX:+UseG1GC -XX:MaxGCPauseMillis=200
    
  • 操作系统网络调优:增大TCP缓冲区、启用TCP快速打开,减少网络握手与传输延迟:
    sysctl -w net.core.rmem_max=16777216
    sysctl -w net.core.wmem_max=16777216
    sysctl -w net.ipv4.tcp_fastopen=3
    
  • 异步日志输出:将同步日志改为异步(如Logback AsyncAppender),避免磁盘IO阻塞推送线程。

六、请求分发优化

  • 分片处理设备列表:将100万设备拆分为10-20个批次,用独立的HTTP客户端实例或线程池处理每个批次,避免单客户端的并发瓶颈。
  • 全链路非阻塞:确保Payload序列化、错误处理等所有环节均为非阻塞操作,禁用任何Future.get()同步调用,全部依赖ListenableFuture回调处理结果。

内容的提问来源于stack exchange,提问作者A Greenwood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:31:17