1

J'utilise amazon PHP SDK V3.13.1, je dois envoyer au minimum 10 000 notifications push dans les 30 secondes. En ce moment j'utilise la méthode publishAsync c'est plus rapide mais je ne l'ai pas envoyé dans le temps.
J'ai donc implémenté le socket et envoyé un paquet de 3500 push pour chaque fois. Voici ma fonction de contrôleur d'où j'envoie la demande de socket.Envoyer une grande quantité de notification en utilisant SNS PHP-SDK

$parts = parse_url(base_url() . "welcome/send_signal"); 
for ($i = 1; $i <= 10000; $i++) { 
    $device_type_ids_arr[$i]['token_id'] = "User token"; 
    $device_type_ids_arr[$i]['arn'] = "User arn"; 
    $device_type_ids_arr[$i]['member_id'] = $i; 
    if ((count($device_type_ids_arr) == 3500) || $i == 10000) { 
     $postData['devices'] = $device_type_ids_arr; 
     $postData['pushSet'] = $pushSet; 
     $postData['push_content'] = $push_content; 
     $post_string = http_build_query($postData); 
     $device_type_ids_arr = array(); 
     $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 600); 
     if (!$fp) { 
      echo "Some thing Problem"; 
     } 
     $out = "POST " . $parts['path'] . " HTTP/1.1\r\n"; 
     $out .= "Host: " . $parts['host'] . "\r\n"; 
     $out .= "User-Agent: " . $_SERVER['HTTP_USER_AGENT'] . "\r\n"; 
     $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; 
     $out .= "Content-Length: " . strlen($post_string) . "\r\n"; 
     $out .= "Connection: Close\r\n\r\n"; 
     $out .= $post_string; 
     fwrite($fp, $out); 
     fclose($fp); 
    } 
} 

Voici ma fonction qui reçoit les données de socket et envoie une notification push.

$sns = new Aws\Sns\SnsClient(array(
    'version' => 'latest', 
    'key' => "my sns key", 
    'secret' => "secret", 
    'region' => "region", 
    'profile' => "amazon_user_profile", 
    'debug' => false, 
    'http' => array('verify' => false) 
     )); 
foreach ($device_id_arr as $device_detail) { 
    try { 
     $promises[] = $sns->publishAsync(array(
      'Message' => '{ "GCM": "{\"data\": { \"message\": \"Hello user\" } }"}', 
      'MessageStructure' => 'json', 
      'TargetArn' => "member sns arn" 
     )); 
    } catch (Exception $e) { 
     $errorMsg = $e->getMessage(); 
    } 
} 
$results = \GuzzleHttp\Promise\settle($promises)->wait(TRUE); 
$fp = fopen("test_parallel.txt", "a+"); 
fwrite($fp, "result:" . print_r($results, true) . "\r\n"); 
fclose($fp); 

Quand j'envoie 10 avis que cela fonctionne très bien mais quand j'ai envoyé 3500 pousser alors il ne fonctionne pas et ne me donne pas de réponse. J'ai aussi essayé cette méthode. Amazon AWS PHP SDK with Guzzle's MultiCurl? mais il me donne l'erreur Argument 1 passed to Aws\AwsClient::execute() must implement interface Aws\CommandInterface, array given

$sns = new Aws\Sns\SnsClient(array(
    'version' => 'latest', 
    'key' => "my sns key", 
    'secret' => "secret", 
    'region' => "region", 
    'profile' => "amazon_user_profile", 
    'debug' => false, 
    'http' => array('verify' => false) 
     )); 
foreach ($device_id_arr as $device_detail) { 
    try { 
     $publishCommands[] = $sns->getCommand('Publish', array(
      "Message" => '{ "GCM": "{\"data\": { \"message\": \"' . $push_content . '\", \"type\": \"' . PUSH_TYPE_SIGNAL . '\" } }"}', 
      "MessageStructure" => "json", 
      "TargetArn" => $device_detail['arn'] 
     )); 
    } catch (Exception $e) { 
     $errorMsg = $e->getMessage(); 
    } 
} 
try { 
    $successfulCommands = $sns->execute($publishCommands); 
    $failedCommands = array(); 
} catch (\Guzzle\Service\Exception\CommandTransferException $e) { 
    $successfulCommands = $e->getSuccessfulCommands(); 
    $failedCommands = $e->getFailedCommands(); 
} 

foreach ($failedCommands as $failedCommand) { 
    $fp = fopen("test_parallel4.txt", "a+"); 
    fwrite($fp, "result:" . print_r($result, true) . "\r\n"); 
    fclose($fp); 
} 

$messageIds = array(); 
foreach ($successfulCommands as $successfulCommand) { 
    $messageIds[] = $successfulCommand->getResult()->get('MessageId'); 
} 

Alors quelqu'un a une solution pour cela? Ma principale préoccupation est d'envoyer des milliers de notifications push dans les 30 secondes.

Répondre

0

Enfin, j'ai obtenu la solution en utilisant multiple curl in php. Ceci est exécuté en parallèle, cela dépend également de votre serveur et de votre vitesse Internet. Voici ma fonction .

public function index() { 
    for ($i = 1; $i <= 10000; $i++) { 
     $device_type_ids_arr[$i]['member_id'] = $i; 
     $device_type_ids_arr[$i]['arn'] = "member arn or empty"; 
     $device_type_ids_arr[$i]['token_id'] = "member token"; 
    } 

    $start = microtime(true); 
    /* Chunk members into 500 bunch and crete multiple curl request */ 
    $_datas = array_chunk($device_type_ids_arr, 500); 
    $mh = curl_multi_init(); 
    $handles = array(); 
    foreach ($_datas as $batchPart) { 
     $ch = curl_init(); 
     $postData['devices'] = $batchPart; //device array 
     $postData['push_content'] = "Push Message"; 
     $data_string = json_encode($postData); 
     curl_setopt($ch, CURLOPT_URL, base_url() . "Welcome/send_push_notification"); 
     curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 
     curl_setopt($ch, CURLOPT_USERAGENT, 'User-Agent: curl/7.39.0'); 
     curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); 
     curl_setopt($ch, CURLOPT_HEADER, 0); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); 
     curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Content-Type: application/json', 
      'Content-Length: ' . strlen($data_string)) 
     ); 
     curl_multi_add_handle($mh, $ch); 
     $handles[] = $ch; 
    } 
    // execute requests and poll periodically until all have completed 
    $isRunning = null; 
    do { 
     curl_multi_exec($mh, $isRunning); 
     usleep(250000); 
    } while ($isRunning > 0); 

    curl_multi_close($mh); 
    printf("Elapsed time: %.2f seconds\n", microtime(true) - $start); 
} 

Voici une fonction qui envoie des notifications push parallèlement. J'explique également comment gérer Exception et m'assurer que les notifications sont envoyées à tous les utilisateurs/maximum.

public function send_push_notification() { 
     require_once APPPATH . 'libraries/aws-sdk/aws-autoloader.php'; 
     $pipeArr = json_decode(file_get_contents('php://input'), true); 
     $push_content = $pipeArr["push_content"]; 
     $device_id_arr = $pipeArr["devices"]; 
     $sns = new Aws\Sns\SnsClient(array(
      'version' => 'latest', 
      'key' => "Amazon account key", 
      'secret' => "Amazon account secret", 
      'region' => "Region", 
      'profile' => "Amazon account user profile", 
      'debug' => false, 
      'http' => array('verify' => false) 
     )); 
     $appArn = "Application Arn"; 
     $promises = $results = $retArr = array(); 
     //start sending loop of 500 members asynchroniously 
     foreach ($device_id_arr as $key => $device_detail) { 
      $arn = $device_detail['arn']; 
      $token = $device_detail['token_id']; 
      $userid = $device_detail['member_id']; 
      //If member arn is empty then register it on amazon and then update into databse 
      if (empty($arn)) { 
       try { 
        $updatedArn = $sns->createPlatformEndpoint(array('PlatformApplicationArn' => $appArn, 'Token' => $token)); 
        $arn = isset($updatedArn['EndpointArn']) ? $updatedArn['EndpointArn'] : ""; 
        //update member detail with new arn into database 
        ($arn != "") ?/* DB query goes here */ : ""; 
       } catch (Exception $e) { 
        $errorMsg = $e->getMessage(); 
       } 
      } 
      if (!empty($arn)) { 
       try { 
        $promises[$userid] = $sns->publishAsync(array(
         'Message' => '{ "GCM": "{\"data\": { \"message\": \"' . $push_content . '\"}}"}', 
         'MessageStructure' => 'json', 
         'TargetArn' => $arn 
        )); 
        $promises[$userid]->arn = $arn; 
        $promises[$userid]->token = $token; 
       } catch (Exception $e) { 
        $errorMsg = $e->getMessage(); 
       } 
      } 
     } 
     //This is Async method to send push and get result of each member with message Id 
     $results = \GuzzleHttp\Promise\settle($promises)->wait(TRUE); 

     /* Handle result and get message Id */ 
     foreach ($results as $key => $value) { 
      /* If any of push notification is fail then check for error and fix it */ 
      if (isset($value['reason'])) { 
       $message = $value['reason']->getMessage(); 
       $token = (isset($promises[$key]->token)) ? $promises[$key]->token : ""; 
       $arn = (isset($promises[$key]->arn)) ? $promises[$key]->arn : ""; 
       if (strpos($message, "Endpoint is disabled") !== false && $token != "" && $arn != "") { 
        try { 
         $res = $sns->setEndpointAttributes(array(
          'Attributes' => array("Token" => $promises[$key]->token, "Enabled" => "true"), 
          'EndpointArn' => $arn 
         )); 
        } catch (Exception $e) { 
         $errorMsg = $e->getMessage(); 
        } 
       } 
       if (strpos($message, "No endpoint found for the target arn specified") !== false && $token != "") { 
        try { 
         $updatedArn = $sns->createPlatformEndpoint(array('PlatformApplicationArn' => $appArn, 'Token' => $token)); 
         $arn = isset($updatedArn['EndpointArn']) ? $updatedArn['EndpointArn'] : ""; 
         //update member detail with new arn into database 
         ($arn != "") ?/* DB query goes here */ : ""; 
        } catch (Exception $e) { 
         $errorMsg = $e->getMessage(); 
        } 
       } 
       if (!empty($arn)) { 
        try { 
         $publishRes = $sns->publish(array(
          'Message' => '{ "GCM": "{\"data\": { \"message\": \"' . $push_content . '\", \"type\": \"' . PUSH_TYPE_SIGNAL . '\" } }"}', 
          'MessageStructure' => 'json', 
          'TargetArn' => $arn 
         )); 
         $retArr[$key] = $publishRes->get("MessageId"); 
        } catch (Exception $e) { 
         $errorMsg = $e->getMessage(); 
         /* Final error of push notification not sent */ 
         $newFile = fopen("error_push_not_sent.txt", "a+"); 
         fwrite($newFile, "Member Id:" . $key . "\r\nARN:" . $arn . "\r\nToken:" . $token . "\r\n" . $errorMsg . "\r\n"); 
         fclose($newFile); 
        } 
       } 
      } else { 
       $retArr[$key] = $results[$key]['value']->get("MessageId"); 
      } 
     } 

     /* Get message Id of amazon and insert record into database */ 
     if (isset($retArr) && !empty($retArr)) { 
      foreach ($retArr as $member_id => $message_id) { 
       /* DB query goes here OR you can generate batch query here and then execute */ 
      } 
     } 
    }