我已经实现了c2dm,它可以正常工作,收到消息和一切。 然而,有一个问题我无法找到解决方案。
当某个事件发生时,我想快速将相同的消息推送到几千个设备,最好是在一分钟内。我知道无法确定是否会传递此消息,并且Google可能会因不同情况而延迟发送消息。
我的iOS实现大致相同,当然发送部分除外。对于15000条消息,大约需要5秒。对于5000封到Android的消息,这需要花费一个多小时才能实现。
有谁知道加快这个速度的方法? 或者谷歌是否会阻止此类大规模推送以阻止垃圾邮件?
代码的C2DM部分如下。这是在PHP中,但我读大多数其他编程语言没有问题。 我使用脚本连接()一次然后循环所有标记并使用sendMessage()发送每条消息。发送完所有消息后,它会断开连接()。
<?php
class C2DMclient
{
private $authKey = NULL;
private $ch = NULL;
function connect() {
$post_params = array(
'Email' => 'C2DM_USER',
'Passwd' => 'C2DM_PWD',
'accountType' => 'HOSTED_OR_GOOGLE',
'source' => 'appname',
'service' => 'ac2dm',
);
$first = true;
$data_msg = '';
foreach($post_params as $key => $value) {
if($first)
$first = false;
else
$data_msg .= '&';
$data_msg .= urlencode($key).'='.urlencode($value);
}
$x = curl_init('C2DM_CLIENTLOGIN');
curl_setopt($x, CURLOPT_HEADER, true);
curl_setopt($x, CURLOPT_POST, true);
curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg);
curl_setopt($x, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($x);
curl_close($x);
$pos = strpos($response, 'Auth=');
$this->authKey = trim(substr($response, 5 + $pos));
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_URL, 'C2DM_SERVER');
}
function disconnect() {
curl_close($this->ch);
$this->authKey = NULL;
}
function sendMessage($deviceToken, $message) {
$data = array(
'registration_id' => $deviceToken,
'collapse_key' => 'ck_type',
'data.type' => 'TYPE',
'data.message' => $message,
'data.title' => 'Title'
);
$headers = array('Authorization: GoogleLogin auth='.$this->authKey);
if($headers)
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($this->ch, CURLOPT_POST, true);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
$messagedata = curl_exec($this->ch);
return TRUE;
}
}
?>
修改 新解决方案基于curl_multi_exec。
在循环访问数据库查询结果时收集卷曲句柄。在收集了几百个卷曲句柄之后,调用sendMessages($ chs)来发送所有这些消息。目前我在发送之前收集了700条消息,并且似乎具有良好的传送速度和足够快,~10秒发送5000条消息。较高的数字似乎会影响交付率。
<?php
class C2DMclient
{
private $authKey = NULL;
private $ch = NULL;
function connect() {
$post_params = array(
'Email' => 'C2DM_USER',
'Passwd' => 'C2DM_PWD',
'accountType' => 'HOSTED_OR_GOOGLE',
'source' => 'appname',
'service' => 'ac2dm',
);
$first = true;
$data_msg = '';
foreach($post_params as $key => $value) {
if($first)
$first = false;
else
$data_msg .= '&';
$data_msg .= urlencode($key).'='.urlencode($value);
}
$x = curl_init('C2DM_CLIENTLOGIN');
curl_setopt($x, CURLOPT_HEADER, true);
curl_setopt($x, CURLOPT_POST, true);
curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg);
curl_setopt($x, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($x);
curl_close($x);
$pos = strpos($response, 'Auth=');
$this->authKey = trim(substr($response, 5 + $pos));
}
function getMessageCurlHandle($deviceToken, $message) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'C2DM_SERVER');
$data = array(
'registration_id' => $deviceToken,
'collapse_key' => 'ck_type',
'data.type' => 'TYPE',
'data.message' => $message,
'data.title' => 'Title'
);
$headers = array('Authorization: GoogleLogin auth='.$this->authKey);
if($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
return $ch;
}
function sendMessages($chs) {
$mh = curl_multi_init();
foreach($chs as $ch) {
curl_multi_add_handle($mh, $ch);
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while($mrc == CURLM_CALL_MULTI_PERFORM);
while($active && $mrc == CURLM_OK) {
if(curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
curl_multi_close($mh);
}
}
?>
答案 0 :(得分:4)
[更新] C2DM现在是deprecated。它的继任者Google Cloud Messaging (GCM)支持multiple receivers又称批量发送:
{ "data": {
"score": "5x1",
"time": "15:10"
},
"registration_ids": ["4", "8", "15", "16", "23", "42"]
}
<强> [/更新] 强>
C2DM doesn't support批量发送。
但是你可以同时向C2DM服务器发送几个POST请求, 遗憾的是PHP本身不支持多线程。
查看curl_multi_exec,它可以同时发出多个cURL请求。
答案 1 :(得分:0)
我也会调查Firebase,我最近一直在和他们一起玩,看起来很快。它们具有适用于各种框架的API。他们的目标是非常快速地将更改推送到数据集(消息是一个完美的示例),因此当发生更改时,他们会向所有连接的用户发送通知消息。