Amazon's SQS provides the basic functions of a message queueing system. Although SQS is not designed to replace an enterprise-grade messaging system, it does have a variety of useful features. This article looks at the methods in the Zend Framework that make it easy to work with messages and queues in SQS.
In this article, you'll see how to do several important tasks with the Simple Queue Service. As with all of the articles in this series, you'll get the most out of the examples if you have the Zend Framework installed before you begin. If you don't have it installed, download and install the full package from Zend.com (see Resources). This installs the Zend Framework, PHP, and the Apache Web server on your machine. When the install is complete, go to http://localhost/ZendServer/. See the Zend Framework installation documentation for the details. If you can log in to the ZendServer console, you're all set.
You'll also need to set up an account with Amazon (see Resources).
The examples use the PHP Credentials class created in Part 1. That class manages the credentials for your Amazon
account. The credentials are stored in an .ini
file:
Listing 1. Storing credentials in a PHP .ini file
; Configuration file to hold secret keys, account numbers and other useful
; strings for Amazon and other cloud accounts.
[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012
|
SQS only uses your access key and secret key. You don't need to know your owner ID, but your owner ID becomes part of the queue name when you create a message queue.
The sample application consists of a single PHP
page (sqs.php) that performs several functions:
- Lists all the message queues in an account, including the number of messages in each one
- Creates a message queue
- Creates a message and puts it into a queue
- Receives a message from a given queue
- Deletes a received message
- Deletes a message queue along with any messages in it.
To get things started, create a Zend_Service_Amazon_Sqs
object.
Listing 2. Creating a
Zend_Service_Amazon_Sqs object
require_once 'Zend/Service/Amazon/Sqs.php';
require_once 'Credentials.php';
$creds = new Credentials;
$sqs = new Zend_Service_Amazon_Sqs($creds->getCredential('amazon', 'accessKey'),
$creds->getCredential('amazon', 'secretKey'));
|
This
object lets you work with the queues associated with your account. The
Zend_Service_Amazon_Sqs->getQueues() method
returns an array of all the queue names owned by your account. The PHP
page displays those in a table:
Figure 1. Listing your SQS queues
The names of the message queues include the owner ID of your account. In
this example, the queues belong to the owner ID 123456789012. You have to use the fully qualified queue name
(http://queue.amazonaws.com/ownerId/queueName)
when you access a queue or a message. The part of the table visible here
also includes the number of visible messages in each queue. The PHP code
looks like this:
Listing 3. Getting the list of queues and the number of messages in each
$queues = $sqs->getQueues();
foreach ($queues as $queue) {
try {
$messageCount = $sqs->count($queue);
echo "<tr>";
echo "<td>".$queue."</td>";
echo "<td style='text-align: center;'>".$messageCount."</td>";
|
The code uses the count() method to see how many
messages are in each queue. (To be precise, it's the approximate number of
messages; more about that in a minute.) If the queue has at least one
message, PHP creates a button to receive the next message; otherwise, the
cell is blank (see Figure 2).
Listing 4. Creating a button to receive the next message
echo "<td>";
if ($messageCount) {
echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>";
echo "<input type='hidden' name='getNextMessage' value='1'>";
echo "<input type='hidden' name='queueToUse' value='$queue'/>";
echo "<input type='submit' value='Receive Next Message'>";
echo "</form>";
}
else
echo " ";
echo "</td>";
|
The final cell in each row of the table creates a button to delete the queue and any messages in it. The complete table of queues looks like Figure 2.
Figure 2. The complete table of queues
In this screen capture, there are three queues. The two queues that contain messages are displayed with a "Receive Next Message" button. Each row of the table has a "Delete Queue" button to delete a particular queue.
Creating a queue is straightforward. Simply get the
queue name and call the Zend_Service_Amazon_Sqs->create() method. The PHP page
includes a simple form to enter a queue name:
Figure 3. Creating a queue
The code to create a new queue is straightforward.
Listing 5. Creating a queue
try {
$responseCode = $sqs->create($_POST['queueToCreate']);
if ($responseCode)
echo "The queue ".$_POST['queueToCreate']." was created successfully.";
. . .
}
catch (Zend_Service_Amazon_SQS_Exception $sqse) {
echo "The queue could not be created. The error message from Amazon is:";
echo "<br/><br/><i>".$sqse->getMessage()."</i>";
}
|
Zend does not provide any special error handling for the create() method, so the code simply writes the details of the
exception to the page if anything goes wrong. Creating a queue with an
illegal name (queue#3, for example) returns the
exception InvalidParameterValue, while creating one with a
duplicate name returns QueueAlreadyExists. When the queue is
created successfully, the page starts with a success message.
Listing 4. Queue created successfully
The PHP page also has a short form for creating a message.
Figure 5. Creating a message
Notice that the drop-down list is populated with the queue names in your account.
Figure 6. Listing all of the queues in your account
The PHP code to build the drop-down list looks like Listing 6.
Listing 6. Creating a drop-down list of all the queues
<p>Select a queue:</p>
<select name="queueForNewMessage">
<?php
foreach ($queues as $queue) {
echo "<option>".$queue."</option>";
}
?>
</select>
</code>
|
The code to create a new message uses the send()
method.
Listing 7. Sending a message to a queue
try {
$response = $sqs->send($_POST['queueForNewMessage'], $_POST['newMessage']);
if ($response) {
echo "The new message was successfully created in queue ";
echo $_POST['queueForNewMessage'];
echo ".<br/>The message ID is ".$response.".";
}
else {
echo "The new message could not be created in queue ";
echo $_POST['queueForNewMessage'];
echo ".";
}
}
catch (Zend_Service_Amazon_SQS_Exception $sqse) {
echo "The message could not be created. The error message from Amazon is:";
echo "<br/><br/><i>".$sqse->getMessage()."</i>";
}
|
The code sends the request to Amazon. If anything goes wrong while creating the message, the page displays an exception. In most cases, the page displays the ID of the successfully created message.
Figure 7. Message created successfully
The success message includes the ID of the new message. You'll see the message ID again later when you receive the message.
A few words about propagation latency
One of the issues in distributed systems like SQS is propagation latency. For the sake of performance and reliability, most cloud providers have multiple copies of your information scattered around their networks. The positive side of this design is that if a particular machine goes down, your information exists somewhere else in the network. The downside to this approach is that it takes some amount of time for changes to your information to make their way through the network. This delay is called propagation latency. If you install the sample application developed in this article, you'll notice its effects.
When you create a queue, the PHP page displays a success message, indicating that the queue was created successfully. The page also displays a table listing all of the queues in your account. The list of queues returned by SQS typically contains the queue you just created. On the other hand, if you create a message, the table of queues will almost certainly not display the correct number of messages because the message has not made its way to the queue. For example, if you create a new message in a queue that currently has three messages, the data returned by SQS will tell you the message was created successfully, and that there are only three messages in the queue.
To deal with this delay, the page contains a button to refresh the list of queues.
Figure 8. Refreshing the list of queues
If you click this button to refresh the queue, at some point the table will
contain the correct number of messages. (The refresh button allows the
user to update the table without resubmitting the request to create a
message.) For the sample application here, propagation latency can be a
problem when you delete a queue. Even though SQS reports that it deleted
the queue successfully, the name often shows up in the
list. If you ask SQS for the number of messages in that
queue, you'll get an exception. For that reason, the code that generates
the list of queues uses a try block to get the
number of messages in a queue. If the call to the count() method fails, the code simply ignores the exception.
To use SQS effectively, you need to keep the realities of propagation latency in mind. This applies to many other cloud services as well.
There are two steps in processing a message in the queue: receiving it and deleting it. When a message is received, Amazon SQS marks that message as invisible. The message is yours to process, so anyone who accesses the queue won't see it. After you've received a message, it is your responsibility to delete the message within a certain period of time. Each queue is defined with a visibility timeout; if you don't delete the message within that time, the message becomes visible again and can be processed by anyone. The default visibility timeout for a queue is currently 30 seconds.
As an aside, when you create a queue,
Amazon lets you define the visibility timeout for all processed messages.
The Zend Framework supports a second parameter to the Zend_Service_Amazon_Sqs->create() method to define the
visibility
timeout.
Listing 8. Creating a queue with a specified visibility timeout
$responseCode = $sqs->create($_POST['queueToCreate'], 120);
|
In this example, the visibility timeout is 2 minutes.
Receiving a
message from a queue is done with the Zend_Service_Amazon_Sqs->receive() method. The name of the
message queue is passed in from the form. Because a message can be up to
8K characters long, it is displayed in an HTML <textarea> control. A received message has four
parts:
- The
body, the text of the message itself - The
md5digest of the message body - The
message_id, a unique identifier for the message - The
handle, the identifier you must use to delete the message from the queue.
You can access the four parts of the
message with the array keys indicated above. For example, you can use
$message[0]['body'] to get the body of the
message, while $message[0]['handle'] returns
the message handle. Note that although Amazon SQS allows you to ask for
more than one message at a time, the Zend Framework does not. Every call
to Zend_Service_Amazon_Sqs->receive() returns a
single message. The single message is returned in an array, however, so
you have to use $message[0][...] to access the
parts of the message.
Note: Some messaging systems allow you to look at a message without receiving it, an operation usually called peeking. Amazon SQS no longer allows you to peek at messages. The only way to see a message is to receive it.
When you click on the "Receive Next Message" button, you'll see something like Figure 9.
Figure 9. A received message
The visibility timeout is used to generate the sentence, "It will go back into the queue in 30 seconds." More on queue attributes in a minute.
Figure 10. The message handle and the visibility timeout
As mentioned, $message[0]['handle']
returns the handle of the message. You can use the getAttribute() method to return the visibility
timeout.
Listing 9. Finding the visibility timeout for the queue
$visibilityTimeout =
$sqs->getAttribute($_POST['queueToUse'], 'VisibilityTimeout');
|
The
visibility timeout is used to generate the sentence, "It will go back
into the queue in 30 seconds." getAttribute()
lets you find out various details of a queue; more on queue attributes in
a minute.
The form that displays the received message is generated with this code.
Listing 10. Generating the form for a received message
echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>";
// Display the message itself in a <textarea>
echo "The message from the queue is: <br/><br/>";
echo "<textarea cols='80' rows='8'>";
echo $message[0]['body'];
echo "</textarea><br/><br/>";
// The message handle and queue name are hidden fields
echo "<input type='hidden' name='deleteMessage' value='1'/>";
echo "<input type='hidden' name='messageHandle' ";
echo "value='".$message[0]['handle']."'>";
echo "<input type='hidden' name='queueToUse' ";
echo "value='".$_POST['queueToUse']."'>";
// The submit button deletes the message
echo "To delete this message, click here: ";
echo "<input type='submit' value='Delete Message'><br/><br/>";
// Display the message handle if the user wants to delete it later
echo "If you want to delete this message ";
echo "later, use this message handle: <br/><br/>";
echo "<textarea cols='80' rows='3'>";
echo $message[0]['handle']."</textarea><br/><br/>";
// For information, display the visibility timeout of the queue
echo "If you do not delete this message, it will ";
echo "go back into the queue in ".$visibilityTimeout." seconds.";
echo "</form>";
|
As you might have noticed in the previous section, the
form that displays a received message also contains a button to delete the
message. The call to the Zend_Service_Amazon_Sqs->deleteMessage() method requires the
queue name and the message
handle.
Listing 11. Deleting a message from a queue
try {
$response = $sqs->deleteMessage($_POST['queueToUse'],
$_POST['messageHandle']);
echo "The message was deleted successfully.";
}
catch (Zend_Service_Amazon_SQS_Exception $sqse) {
echo "The message could not be deleted. The error message from Amazon is:";
echo "<br/><br/><i>".$sqse->getMessage()."</i>";
}
|
If the message is deleted successfully, the page displays a message.
Figure 11. Successful message deletion
If anything goes wrong, the code simply displays an exception. (Creating a form to let the user delete a message by pasting in the message handle and queue name is left as an exercise for the reader.)
Getting the attributes of a queue
As you saw earlier, the PHP page
displays the visibility timeout of a queue when you receive a message.
This is done by calling getAttribute(). The
first attribute of getAttribute() is the queue
name. For the second argument, Amazon currently supports the following
case-sensitive attribute names:
VisibilityTimeout— The visibility timeout for messages received from the queue.ApproximateNumberOfMessages— The approximate number of messages currently in the queue. This does not include any messages that have been received.ApproximateNumberOfMessagesNotVisible— The approximate number of messages that have been received but not yet deleted.CreatedTimestamp— When the queue was created.LastModifiedTimestamp— The last time the queue's attributes or permissions were changed. Sending, receiving or deleting a message does not change this timestamp.All— Returns all attributes. This is the default.
Note: Be aware that if you call getAttribute() or getAttribute('All'), Zend currently returns the first
attribute only. This bug is likely to be fixed in a future release. For
now, if you want to get all of the attributes of a queue, you'll need to
call getAttribute() for each one. You can
generate a table listing all your queues and their attributes with the
code in Listing 12.
Listing 12. Displaying all your queues and their attributes
<?php
$queues = $sqs->getQueues();
foreach ($queues as $queue) {
try {
echo "<tr>";
echo "<td>".$queue."</td>";
echo "<td style='text-align: center;'>";
echo $sqs->getAttribute($queue, 'VisibilityTimeout');
echo "</td><td style='text-align: center;'>";
echo $sqs->getAttribute($queue, 'ApproximateNumberOfMessages');
echo "</td><td style='text-align: center;'>";
echo $sqs->getAttribute($queue, 'ApproximateNumberOfMessagesNotVisible');
echo "</td><td style='text-align: center;'>";
echo $sqs->getAttribute($queue, 'CreatedTimestamp');
echo "</td><td style='text-align: center;'>";
echo $sqs->getAttribute($queue, 'LastModifiedTimestamp')."</td>";
echo "</tr>";
}
catch (Zend_Service_Amazon_SQS_Exception $sqse) {
}
}
?>
|
The table of attributes looks like this.
Figure 12. All the attributes of a queue
(This code is included in the samples as sqs-attributes.php.)
Deleting a queue deletes the queue and any messages it contains, including messages currently invisible. Because this is such a drastic operation, a confirmation dialog appears before a queue is actually deleted.
Figure 13. Deleting a queue must be confirmed
When PHP generates the form to delete a queue, it defines the confirmation
dialog with the onsubmit attribute of the <form> element.
Listing 13. Creating a button to delete the queue
echo "<td>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='post' ";
echo "onsubmit='return confirm(\"Do you really want to delete the ";
echo "queue $queue? This will delete all any messages in the queue ";
echo "as well.\");'>";
echo "<input type='hidden' name='deleteQueue' value='1'/>";
echo "<input type='hidden' name='queueToDelete' value='$queue'/>";
echo "<input type='submit' value='Delete Queue'>";
echo "</form>";
echo "</td>";
|
If the user clicks the OK button to delete the queue, the queue and all of
the messages it contains are deleted via the delete() method.
Listing 14. Deleting a queue
try {
$response = $sqs->delete($_POST['queueToDelete']);
echo "The queue was deleted successfully.";
}
catch (Zend_Service_Amazon_SQS_Exception $sqse) {
echo "The queue could not be deleted. The error message from Amazon is:";
echo "<br/><br/><i>".$sqse->getMessage()."</i>";
}
|
As with deleting a message, deleting a queue either displays a success message or an exception.
Figure 14. Successful queue deletion
If anything goes wrong, the code simply displays an exception.
There are several operations supported by Amazon SQS
that are not part of the Zend_Service_Amazon_Sqs class. We'll menion those briefly
here, even though they're beyond the scope of the Zend Framework. To
perform any of these tasks, you need to use one of the lower-level APIs
provided by Amazon. The other operations are:
AddPermission: You can define permissions so that other users can access your queues. This allows you to use your queues as a way of coordinating work among different applications.RemovePermission: You can revoke permissions, as well.SetQueueAttributes: Zend allows you to get the attributes of a queue, but it does not allow you to change any of them.ChangeMessageVisibility: After you have received a message, you can change its visibility timeout. This gives you more time to process the message before it returns to the queue. This method only applies to the received message; it does not change the default visibility timeout for the queue itself.
See the SQS documentation for more details on these methods.
This article presented a PHP page that lets you work with Amazon Simple Queue Service. You can use the page to create and delete message queues, send and receive messages, and monitor the status of the queues. The technical details of the actual requests sent to Amazon are hidden behind a PHP object, making it simple to use queues and messages. Using the Zend Framework gives you an elegant set of objects to work with cloud computing.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code | os-php-cloud3-source.zip | 5KB | HTTP |
Information about download methods
Learn
-
You can sign up for an Amazon Web Services
account at the Amazon SQS home
page.
- For specifics
about SQS, including methods not supported by Zend, check out the SQS documentation.
- Discover why cloud computing is important, how
to get started, and where to learn more about it in the developerWorks Cloud computing
space.
-
PHP.net is the central resource for PHP developers.
-
Check out the "Recommended PHP reading list."
-
Browse all the PHP content on developerWorks.
-
Follow developerWorks on Twitter.
-
Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Using a database with PHP? Check out the Zend Core for
IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
-
The My developerWorks community is an example of a successful general community that covers a wide variety of topics.
-
Stay current with developerWorks' Technical events and webcasts.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Download the Zend
framework from Zend.com.
- Download the Zend Server
Community Edition to run the examples in this
article.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.
-
Participate in the developerWorks PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS).
Doug Tidwell is a senior software engineer in IBM's Emerging Technology group. He was a speaker at the first XML conference in 1997, and he has been working with markup languages, Web services and SOA (the technologies beneath the cloud) for many years. His presentations have been featured at dozens of conferences around the world, and his JavaOne presentation on cloud computing earned him a Rock Star award in 2009. His job as a technology evangelist is to explain the standards and technologies behind cloud computing and to help customers integrate them into their overall business architectures and strategies. He is the author of many developerWorks articles, and is the author of O'Reilly's book on XSLT, a copy of which makes a perfect gift for any occasion. He lives in Chapel Hill, N.C., with his wife, daughter, and dog.




