本文介绍如何使用PHP SDK中的sample代码,来完成创建主题、创建队列、创建订阅和发布消息等操作。

步骤一:准备工作

  1. 下载最新版PHP SDK,解压后进入aliyun-mns-php-sdk-master/Samples/Topic子目录。
  2. 打开CreateTopicAndSendMessage.php文件,在文件中最下方配置以下内容:
    • AccessKey ID、AccessKey Secret
    • Endpoint
      • 访问消息服务MNS的接入地址,请登录MNS控制台,单击右上角获取Endpoint查看。
      • 不同地域的接入地址不同。
  3. 修改SDK设置。

    CreateTopicAndSendMessage的代码顶部有一些设置,在使用SDK的时候需要做同样的设置。

    //require SDK里自带的一个autoload文件。
    require_once(dirname(dirname(dirname(__FILE__))).'/mns-autoloader.php');
    
    //代码里需要用的一些PHP class。
    use AliyunMNS\Client;
    use AliyunMNS\Model\SubscriptionAttributes;
    use AliyunMNS\Requests\PublishMessageRequest;
    use AliyunMNS\Requests\CreateTopicRequest;
    use AliyunMNS\Exception\MnsException;       

步骤二:创建主题

如果之前未创建过主题,那么首先需要创建主题。默认创建的主题名称是CreateTopicAndPublishMessageExample,也可以修改代码指定主题名称。

// 1.生成一个CreateTopicRequest实例,参数传入topicName。这里可以同时传入TopicAttributes,以便在CreateTopic时同时设置自定义的Topic属性。
$request = new CreateTopicRequest($topicName);
try
{
        $res = $this->client->createTopic($request);
        echo "TopicCreated! \n";
}
catch (MnsException $e)
{
        // 2.可能因为网络错误,或者Topic已经存在等原因导致CreateTopic失败,这里CatchException并做对应的处理。
        echo "CreateTopicFailed: " . $e . "\n";
        echo "MNSErrorCode: " . $e->getMnsErrorCode() . "\n";
        return;

步骤三:创建队列

如果之前未创建队列,那么首先需要创建队列。默认创建的队列名称是CreateQueueAndSendMessageExample,也可以修改代码指定队列名称。

// 1.首先初始化一个client。
$this->client = new Client($this->endPoint, $this->accessId, $this->accessKey);

// 2.生成一个CreateQueueRequest对象。CreateQueueRequest还可以接受一个QueueAttributes参数,用来初始化生成的queue的属性。
// 对于queue的属性,请参见Queue。
$request = new CreateQueueRequest($queueName);
try
{
        $res = $this->client->createQueue($request);
        // 3.创建队列成功。
        echo "QueueCreated! \n";
}
catch (MnsException $e)
{
        // 4.可能因为网络错误,或者Queue已经存在等原因导致CreateQueue失败,这里CatchException并做对应的处理。
         echo "CreateQueueFailed: " . $e;
         return;
}            

步骤四:创建订阅

在MNS Server创建订阅,主题里面的消息应该推送到哪里。

$regionId = "";
$accountId = "";
$queueName = "TestQueue";
$subscriptionName = "QueueEndpoint";

$attributes = new SubscriptionAttributes($subscriptionName, 'acs:mns:' . $regionId . ':' . $accountId . ':queues/' . $queueName);
try
{
        $topic->subscribe($attributes);
        // 订阅成功。
        echo "Subscribed! \n";
}
catch (MnsException $e)
{
        // 可能因为网络错误,或者同名的Subscription已存在等原因导致订阅出错,这里CatchException并做对应的处理。
        echo "SubscribeFailed: " . $e . "\n";
        echo "MNSErrorCode: " . $e->getMnsErrorCode() . "\n";
        return;
}         

步骤五:发布消息

现在可以发布消息到主题中。

$messageBody = "test";
// 1.生成PublishMessageRequest。如果是推送到邮箱,还需要设置MessageAttributes,可以参照Tests/TopicTest.php里面的testPublishMailMessage。
$request = new PublishMessageRequest($messageBody);
try
{
        $res = $topic->publishMessage($request);
        // 2.发布消息成功。
        echo "MessagePublished! \n";
}
catch (MnsException $e)
{
        // 3.可能因为网络错误等原因导致PublishMessage失败,这里CatchException并做对应处理。
        echo "PublishMessage Failed: " . $e . "\n";
        echo "MNSErrorCode: " . $e->getMnsErrorCode() . "\n";
        return;
}            

步骤六:从队列接收和删除消息

$receiptHandle = NULL;
try
{
        // 1.直接调用receiveMessage函数。
        // receiveMessage函数接受waitSeconds参数,无特殊情况建议设置为30。
        // waitSeconds非0表示这次receiveMessage是一次http long polling,如果queue内没有message,那么这次request会在server端等到queue内有消息才返回。最长等待时间为waitSeconds的值,最大为30。
        $res = $queue->receiveMessage(30);
        echo "ReceiveMessage Succeed! \n";
        if (strtoupper($bodyMD5) == $res->getMessageBodyMD5())
        {
             echo "You got the message sent by yourself! \n";
        }
        // 2.获取ReceiptHandle,这是一个有时效性的Handle,可以用来设置Message的各种属性和删除Message。详细说明,请参见QueueMessage。
        $receiptHandle = $res->getReceiptHandle();
}
catch (MnsException $e)
{
        // 3.和CreateQueue和SendMessage一样,ReceiveMessage也有可能出错,所以加上CatchException并做对应的处理。
        echo "ReceiveMessage Failed: " . $e;
        return;
}

// 这里是您处理消息的逻辑。Sample里就直接略过这一步。
// 如果这里发生了程序崩溃或卡住等异常情况,对应的Message会在VisibilityTimeout之后重新可见,从而可以被其他进程处理,避免消息丢失。

// 4.消息已经处理完成,从队列里删除这条消息。
try
{
        // 5.直接调用deleteMessage。
        $res = $queue->deleteMessage($receiptHandle);
        echo "DeleteMessage Succeed! \n";
}
catch (MnsException $e)
{
        // 6.这里CatchException并做异常处理。
        // 如果是receiptHandle已经过期,那么ErrorCode是MessageNotExist,表示通过这个receiptHandle已经找不到对应的消息。
        // 为了保证receiptHandle不过期,VisibilityTimeout的设置需要保证足够消息处理完成。并且在消息处理过程中,也可以调用changeMessageVisibility这个函数来延长消息的VisibilityTimeout时间。
        echo "DeleteMessage Failed: " . $e;
        return;
}            

步骤七:删除主题

删除测试用的主题。

try
{
        $this->client->deleteTopic($topicName);
        echo "DeleteTopic Succeed! \n";
}
catch (MnsException $e)
{
        echo "DeleteTopic Failed: " . $e;
        return;
}            

步骤八:删除队列

删除测试用的队列。

try {
        $this->client->deleteQueue($queueName);
        echo "DeleteQueue Succeed! \n";
} catch (MnsException $e) {
        echo "DeleteQueue Failed: " . $e;
        return;
}