Android, быстро отправляйте сообщения на 1000 устройств - PullRequest
5 голосов
/ 09 января 2012

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

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

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

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

Часть кода C2DM приведена ниже.Это на PHP, но у меня нет проблем с чтением большинства других языков программирования.Я использую скрипт для connect () один раз, затем зацикливаю все токены и использую 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.

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

Ответы [ 2 ]

4 голосов
/ 09 января 2012

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

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

[/ Update]

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

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

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

0 голосов
/ 17 декабря 2013

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

https://www.firebase.com/

...