2012-01-09 10 views
5

私はc2dmを実装しており、デバイスがメッセージとすべてを受信するようにうまく動作します。 解決策が見つからないという問題が1つあります。Android、1000個のデバイスに高速にメッセージを送信

特定のイベントが発生した場合、同じメッセージを数千のデバイスに素早く、できれば1分以内にプッシュしたいと考えています。メッセージが配信されることは確実ではなく、状況によってはGoogleがメッセージを遅らせる可能性があることはわかっています。

iOSの実装は、送信部を除いてほぼ同じです。それは15000メッセージに対して約5秒かかります。 Androidへの5000件のメッセージには1時間以上かかりますが、これは長いです。

誰かがこれをスピードアップする方法を知っていますか? Googleはこのような大量攻撃を阻止してスパムを阻止していますか?

コードのC2DM部分は次のとおりです。これはPHPで書かれていますが、他のほとんどのプログラミング言語を読んでも問題はありません。 私はconnect()を一回実行した後にすべてのトークンをループし、sendMessage()を使って各メッセージを送信するスクリプトを使用します。すべてのメッセージが送信されると、disconnect()が呼び出されます。

<?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に基づいています。

データベースクエリー結果をループしながら、カールハンドルが収集されます。数百のカールハンドルが集められた後、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); 
    } 
} 
?> 

答えて

4

[更新] C2DMは今deprecatedです。

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

[/更新]

C2DMまだ送信doesn't supportバッチ:それは後継Google Cloud Messaging (GCM)が送信multiple receivers別名バッチをサポートしています。

しかし、 残念ながら、PHPはそれ自身がマルチスレッドをサポートしていません。同時に、C2DMサーバーに複数のPOSTリクエストを送信することもできます。

curl_multi_execを見ると、複数のcURLリクエストを同時に行うことができます。

+0

私はC2DMは、バッチ送信し、そのための私はメッセージごとに1つのPOSTを行うことをサポートしていないことを知っています。何らかの理由でこのプロセスには本当に時間がかかります。私はcurl_multi_execを見ていきます。たぶんそれは多くの時間を取るカールそのものです。私はもう少し時間があり、何か興味深いものが見つかると戻ってきます。 – Daniel

+0

curl_multi_execが解決策に見えました。数日間テストした後、5000メッセージを送信する時間は1時間以上から数秒になりました。しかし、メッセージがメッセージを受け取る場合はかなりランダムです。途中で失われそうな人もいます。私は一度に2000のメッセージがたくさんあると思うし、最適なパフォーマンスとスピードのためにこれを微調整しようとします。私は時間が来たら元の投稿を更新します。 – Daniel

0

また、私はFirebaseを調査するつもりです。最近、私はそれらをかなり使っています。彼らは非常に幅広いフレームワークのAPIを持っています。彼らの目標は、データセットへの変更を非常に迅速にプッシュすることです(メッセージは完全な例です)。変更が発生したときに、接続されたすべてのユーザーに通知メッセージが送信されます。

https://www.firebase.com/

関連する問題