Android, быстрые сообщения на 1000 устройств

Я реализовал c2dm, и он отлично работает, что устройство получает сообщение и все такое. Однако есть одна проблема, из-за которой я не могу найти решение.

Когда происходит определенное событие, я хочу быстро отправить одно и то же сообщение на несколько тысяч устройств, предпочтительно в течение одной минуты. Я знаю, что нет уверенности в том, что сообщение будет доставлено и что Google может задержать сообщение из-за разных обстоятельств.

Моя реализация для iOS примерно такая же, за исключением, конечно, отправляющей части. Это занимает около 5 секунд для 15000 сообщений. Для 5000 сообщений для Android требуется более часа, что является долгой.

Кто-нибудь знает способ ускорить это? Или Google останавливает этот массовый толчок, чтобы остановить спам?

Часть кода 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; } } ?> 

EDIT: новое решение основано на curl_multi_exec.

Обработки curl собираются во время цикла по результатам запроса базы данных. После того, как собрано несколько сотен ручек, 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); } } ?> 

[Обновление] C2DM теперь устарел . Это преемник Google Cloud Messaging (GCM) поддерживает несколько приемников, а также пакетную отправку:

 { "data": { "score": "5x1", "time": "15:10" }, "registration_ids": ["4", "8", "15", "16", "23", "42"] } 

[/Обновить]

C2DM еще не поддерживает пакетную отправку.

Однако вы можете отправить несколько запросов POST на сервер C2DM одновременно, к сожалению, PHP не поддерживает многопоточность.

Посмотрите на curl_multi_exec, который дает возможность делать несколько запросов cURL одновременно.

Вы можете использовать выделенный Push-сервер, поддерживающий Android и iOS. Например, с Lightstreamer (www.lightstreamer.com) вы можете вывести сообщение на тысячи устройств за несколько миллисекунд. [Полное раскрытие: Я – технический директор Lightstreamer]

Также я бы исследовал Firebase, я играл с ними совсем немного в последнее время, и это кажется очень быстрым. У них есть API для довольно широкого спектра фреймворков. Их цель – очень быстро внести изменения в набор данных (сообщения – прекрасный пример), поэтому, когда происходит изменение, они отправляют уведомление всем связанным пользователям.

https://www.firebase.com/