Simple Queue Service

Amazon Simple Queue Service provides a simple way to set up queues of messages that you can use for managing workflows or queuing up work to do. This PHP class is a convenient REST-based interface to that service.

A bit of example code will be a good demonstration of how simple this class is to use. Please read through these examples, and then feel free leave a comment if you have any questions or suggestions.

This document is based on version 1.0.0 of the SQS class, which is designed to use API version 2009-02-01. If you’ve been using 0.9.2, remember that 1.0.0 is not backward-compatible. You should still be able to use 1.0.0 to access queues you created with 0.9.2, since the AWS API versions they use are compatible, but I have not actually tested that. Also note that unlike 0.9.2, the new version cannot be used statically, and by default it uses SSL for createQueue and listQueues.

So, let’s get started. First, you’ll need to create an SQS object:

require_once('sqs.php');
$sqs = new SQS('Access Key Here', 'Secret Key Here');

If you don’t already have a queue, you’ll want to create one:

$response = $sqs->createQueue('testQueue');
$queue = $response['QueueUrl'];
print_r($response);
-------
Array
(
    [QueueUrl] => https://sqs.us-east-1.amazonaws.com/123456789012/testQueue
    [RequestId] => 7b20a1b9-30eb-412a-b3e9-62102eb0da28
)

Every request to SQS will include a request identifier in the response. If you need to contact AWS about problems with a particular request, you can provide a relevant request identifier to give them more information to work with.

createQueue also optionally accepts a second parameter which sets the queue’s default message visibility timeout, in seconds, if you want to override the default value.

Note that by default, this class uses SSL. At the end of this document I’ll explain how to override that behavior.

Alternatively, if you want to get the URL of an existing queue, you can list the queues on your account:

$response = $sqs->listQueues();
$queue = $respose['Queues'][0];
print_r($response);
-------
Array
(
    [RequestId] => 790fcea6-3df5-4a88-aef7-08964164239e
    [Queues] => Array
        (
            [0] => https://sqs.us-east-1.amazonaws.com/123456789012/testQueue
        )
)

The QueueUrl in the createQueue or listQueues response is the value you’ll need for all the rest of the calls. Note that this URL is not just the queue name you chose in the createQueue call; instead it is a composite value including the request method (HTTP or HTTPS), the SQS endpoint, your AWS account ID, and the queue name. You need to use this full value to interact with your queue.

Now that we have a queue, let’s send a message:

print_r($sqs->sendMessage($queue, 'This is a test message')));
-------
Array
(
    [RequestId] => 21d1ade3-8155-477d-89df-27f62ba1c28b
    [MD5OfMessageBody] => fafb00f5732ab283681e124bf8747ed1
    [MessageId] => 9f9acefd-01da-46db-adb5-40af35dfc7c6
)

If you want, you can use the MD5OfMessageBody element of the response to verify that your message was received correctly by SQS.

After waiting around 30 seconds, you should be able to retrieve the message you just posted:

$messages = $sqs->receiveMessage($queue);
print_r($message);
-------
Array
(
    [RequestId] => 0c8873fb-4cc9-448c-8ccf-c47386ada8ff
    [Messages] => Array
        (
            [0] => Array
                (
                    [MessageId] => 9f9acefd-01da-46db-adb5-40af35dfc7c6
                    [ReceiptHandle] => +eXJYhj5rDp/nuICOhmUlU2FDPkkD0EakC69z4M8ETl0DJ3gVOmjI2Gh/oFnb0IeJqy5Zc8kH4JARkzdFBpldzaAPSeOkXQZ613q3nEK3/fYDe0gheqkcx7CJOIiU743A19ENUGSgTpADQFIpn7IOgSCsMbsyUkKW+UUMXRDpAI=
                    [MD5OfBody] => fafb00f5732ab283681e124bf8747ed1
                    [Body] => This is a test message
                )
        )
)

By default, receiveMessage will retrieve up to ten messages from the queue. You can see here that the MessageId field matches what we got from the sendMessage call, as do the MD5OfBody and Body fields. Once you have a message, you’ll do whatever processing you need, and then you’ll want to delete the message from the queue.

However, you don’t use the MessageId to do that, you use the ReceiptHandle, like this:

$m = $messages['Messages'][0];
$sqs->deleteMessage($queue, $m['ReceiptHandle']);

deleteMessage will return a request id if you need it.

That’s all there is to it! There are, of course, several other things you can do with your queues. I’ll summarize them here, but I won’t provide sample output in the interest of brevity.

You can retrieve the attributes set on your queue, or a specific attribute if you know which one you’re interested in (see the GetQueueAttributes documentation for a list of possible attributes):

print_r($sqs->getQueueAttributes($queue));
print_r($sqs->getQueueAttributes($queue, 'ApproximateNumberOfMessages'));

You can set one or more attributes, as well (see the SetQueueAttributes documentation for a list of attributes you can set):

$attributes = array();
$attributes['VisibilityTimeout'] = 180;
$attributes['MaximumMessageSize'] = 65536;
// etc
$sqs->setQueueAttributes($queue, $attributes);

If you’ve received a message, but you’re not ready to delete it and you don’t want the message to become visible again in the queue, you can change the visibility for a specific message:

$sqs->changeMessageVisibility($queue, $message['ReceiptHandle'], $new_visibility_timeout);

You can share your queue with other AWS accounts, giving them access to specific operations. You pass in a unique label of your choice, and a list of permissions you want to associate with the label. The permissions array should be a mapping of AWS account ID (not access keys or secret keys!) to the permissions you want to grant:

$permissions = array();
$permissions['125074342641'] = 'SendMessage';
$permissions['125074342642'] = 'ReceiveMessage'];
$sqs->addPermission($queue, 'AccessForJimAndSteve', $permissions);

Note that SQS will reject the request if any of the account IDs are invalid. See the documentation on Shared Queues for more information.

You can of course also remove previously-granted permissions:

$sqs->removePermission($queue, 'AccessForJimAndSteve');

If you no longer need a queue, you can delete it, even if there are still messages in the queue:

$sqs->deleteQueue($queue);

listQueues takes an optional prefix argument, so for example, this call will list all queues that begin with “sprocket”:

print_r($sqs->listQueues('sprocket'));

If you have three queues named sprocketSales, sprocketShipping, and widgetDistribution, then that call would only list the first two.

receiveMessage has three optional arguments in addition to the queue name:

$attributes = array('SentTimestamp', 'SenderId');
$messages = $sqs->receiveMessage($queue, $num_messages, $visibility_timeout, $attributes);

$num_messages can be any number between 1 and 10, and $visibility_timeout overrides the queue’s default visibility timeout for the $num_messages messages it retrieves. $attributes is a list of message attributes to retrieve in addition to the normal message data. See the ReceiveMessage documentation for more information.

Finally, the createQueue and listQueues calls use the endpoint that is set when the SQS object is created, which by default is the us-east-1 endpoint; you can choose a different endpoint if you want. For example, to interact with the us-west-1 endpoint by default, do this:

$sqs = new SQS('AccessKey', 'SecretKey', SQS::ENDPOINT_US_WEST);

The SQS class has some constants you can use instead of having to remember the endpoint URLs yourself:

  • SQS::ENDPOINT_US_EAST
  • SQS::ENDPOINT_US_WEST
  • SQS::ENDPOINT_EU_WEST
  • SQS::ENDPOINT_AP_SOUTHEAST

This class uses HTTPS by default; if you can’t or don’t want to use SSL, you can use these constants instead, which use HTTP rather than HTTPS:

  • SQS::INSECURE_ENDPOINT_US_EAST
  • SQS::INSECURE_ENDPOINT_US_WEST
  • SQS::INSECURE_ENDPOINT_EU_WEST
  • SQS::INSECURE_ENDPOINT_AP_SOUTHEAST

Note that regardless of what endpoint you specify in the constructor, the class will use whatever method and endpoint it finds in the $queue parameter of the various calls. If you have this setup:

$sqs = new SQS('AccessKey', 'SecretKey', SQS::ENDPOINT_EU_WEST);
$queue1 = 'https://sqs.us-east-1.amazonaws.com/123456789012/testQueue';
$queue2 = 'http://sqs.ap-southeast-1.amazonaws.com/123456789012/anotherQueue';
$sqs->getQueueAttributes($queue1);
$sqs->getQueueAttributes($queue2);

Both getQueueAttributes calls will do the “right” thing. The first call will connect via HTTPS to the us-east-1 endpoint, and the second will connect insecurely (without SSL) to the ap-southeast-1 endpoint. Neither call cares what the default endpoint was set to in the constructor. The default endpoint is only used if you call createQueue or listQueues.


Disclaimer: Although I work for Amazon (the RDS team, specifically), this class is neither produced, endorsed nor supported by Amazon. I maintain this PHP class as a personal project, just for fun.

3 Comments »

 
  • Eric says:

    Very nice indeed! And great explanations. Thanks for sharing.

  • nbari says:

    Is there a way to have a daemon listening to the queue so when a message arrive can quickly dispatch it ?

    • Dan says:

      You can use cron to run a PHP script at regular intervals to check the queue. If you want a true daemon that can do its own scheduling and polling and whatnot, you probably want to use something that’s not PHP, like C or Java, and it’s more work.

 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
Easy AdSense by Unreal