FCM批量发送服务停用后,循环调用HTTP v1 API是否合规?
关于FCM HTTP v1 API逐条调用的合理性及代码优化建议
核心结论
逐条调用FCM HTTP v1 API是符合谷歌预期的可行方案,但你的当前代码存在几个关键问题需要修正,同时可以通过HTTP/2特性进一步优化性能。
为什么逐条调用是可行的?
谷歌推荐的FCM HTTP v1 API本身就是单条消息发送的设计,结合HTTP/2的多路复用特性,即使发起多个请求,底层也会复用同一个TCP连接,不会像HTTP/1.1那样产生大量连接开销。400条请求在HTTP/2下的性能表现和原批量接口差距不大,甚至在谷歌的扇出优化加持下,送达效率会更稳定。
当前代码的问题
- HTTP版本错误:你已启用HTTP/2,但代码强制设置
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,完全浪费了HTTP/2的多路复用优势,应改为CURL_HTTP_VERSION_2_0。 - Content-Type错误:FCM HTTP v1 API接收JSON格式请求体,不需要
multipart/mixed类型,应改为Content-Type: application/json。 - 变量名不匹配:代码中生成的请求内容是
$data,但POST字段用了未定义的$request,会导致请求体为空,发送失败。 - 资源重复创建:每次循环都初始化和关闭cURL句柄,即使HTTP/2也会影响连接复用效率,应把cURL初始化移到循环外。
- 字段格式错误:FCM的
notification只支持标准字段(如title、body),自定义字段(website_link、notification_type)应放在data对象中,否则客户端可能无法解析。
优化后的代码示例
// 初始化cURL句柄(仅执行一次) $curl = curl_init(); // 设置通用cURL选项 curl_setopt_array($curl, array( CURLOPT_URL => 'https://fcm.googleapis.com/v1/projects/my-app/messages:send', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0, // 启用HTTP/2 CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', // 修正请求类型 'Authorization: Bearer ' . $accessToken ), )); foreach ($deviceTokens as $token) { $data = json_encode(array( "message" => array( "token" => $token, "notification" => array( "title" => "Test", // 使用FCM标准字段名 "body" => "Test", "image" => "https://example.com/test.jpg" // 图片需完整HTTP/HTTPS URL ), "data" => array( // 自定义字段放入data对象 "website_link" => "https://example.com", "notification_type" => "message" ) ) )); // 仅更新循环中变化的POST内容 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); $response = curl_exec($curl); // 建议添加错误检测:if(curl_errno($curl)) { /* 处理错误 */ } echo $response . '<br />'; } // 最后统一关闭cURL句柄 curl_close($curl);
额外注意事项
- 速率限制:FCM有请求速率限制,400条属于小批量一般不会触发,但大批量发送时需监控响应中的
Retry-After头,实现退重逻辑。 - 批量替代方案:如果追求极致效率,可使用FCM的主题订阅或设备组功能,将同类设备分组后一次请求发送给多个设备,但需提前做好设备分组管理。
- 错误处理:建议添加
curl_error()检查请求是否失败,避免静默丢失消息。
内容的提问来源于stack exchange,提问作者labu77
相关产品推荐
相关产品推荐

