After reading Ryan Baxter’s great blog post about using PHP in IBM Bluemix, I decided to experiment with using the MQ Light service from a PHP application.¬† PHP is not an officially supported runtime in Bluemix but Daniel Mikusa’s PHP buildpack is listed as being cloud foundry compatible ¬† and Ryan had success with it. Likewise, PHP is not yet a language that IBM supports for use with the MQ Light API.¬† However, MQ Light is based on AMQP 1.0 and I have previously explained how to use AMQP 1.0 clients such as Apache Qpid Proton with MQ Light.
We have an example application that we use for MQ Light labs called the MQ Light Sentiment Sample. This has a node.js front end which communicates with workers implemented in either Node.JS or java using JMS. I decided to implement a PHP worker and you can see the code I created in the PHP-worker branch.
Extending the PHP Buildpack to include MQ Light support.
Building the Apache Qpid Proton PHP extension.
Daniel’s buildpack is set up to work with a set of common PHP extensions. It does not yet include the facility to pull extensions in and build them dynamically so if you want to use a PHP extension that is not included by default then you have to build that extension yourself. It turns out that the qpid proton PHP extension is not included so I had to build it.¬† The resulting object files are in github in PHP-worker, so you dont have to build them unless you want to but here is how I made them:
IBM Bluemix is based on cloudfoundry which is currently targetted at Ubuntu Lucid (10.4) so I fired up an Ubuntu Lucid VM in which to compile the extension.¬† I followed the qpid proton compilation instructions to get the necessary compile prereqs:
sudo-apt-get update sudo apt-get install gcc cmake uuid-dev libssl-dev swig sudo apt-get install libxml2-dev¬† #required for php to configure
I want to use¬† PHP 5.4 in Bluemix and this is not available packaged for Ubuntu 10.4 so I installed it.
sudo add-apt-repository ppa:ondrej/php5-oldstable sudo apt-get upgrade sudo apt-get update sudo apt-get install php5-cli sudo apt-get install php5-dev
I fetched the Proton 0.7 source from http://qpid.apache.org/components/messenger/index.html and unzipped it.
Fortunately patches are available for those two issues, so I applied them:
patch -p1¬† --ignore-whitespace --binary -u -l < 0001-ensure-messenger-honours-remote-idle-timeout.patch
wget -O proton516.patch "https://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/transport/transport.c?r1=1599791&r2=1599790&pathrev=1599791&view=patch"
patch -p1¬† --ignore-whitespace --binary -u -l < proton516.patch
With these patches in place I compiled proton.
¬†¬†¬† mkdir build ¬†¬†¬† cd build ¬†¬†¬† cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DSYSINSTALL_BINDINGS=ON ¬†¬†¬† make
Sniff testing the Apache Qpid Proton PHP extension with MQ Light on my laptop.
To verify that I had all the code compiled correctly, I installed the standalone MQ Light runtime¬† into my VM from the MQ Light standalone install page – its a simple download and unzip. I then started MQ Light.
To verify that mq qpid proton install was working correctly I¬† used the qpid proton send.php sample.
php php send.php amqp://localhost/mytopic
In the MQ Light GUI I can see that the message “hello world” has been sent to the topic “mytopic”. Note that the client ID shown in the GUI is the UUID that the PHP client created.
Next I connect to a private destination using:
php recv.php amqp://localhost/private:mytopic
I sent another message, and this time it was delivered to my consumer: I can see what has happened in the MQ Light UI
Lastly, I¬† connected 3¬† receives¬† to a shared destination with:
php recv.php amqp://localhost/share:myshare:mytopic & php recv.php amqp://localhost/share:myshare:mytopic & php recv.php amqp://localhost/share:myshare:mytopic &
and send some messages:
send.php amqp://localhost/mytopic send.php amqp://localhost/mytopic send.php amqp://localhost/mytopic
Integrating the build Qpid Proton extension into my Bluemix app so that it will work with the PHP Buildpack.
In order to get the Qpid Proton extension loaded by my Bluemix application I had to extend¬† the buildpack¬†¬†as documented.
The file .extensions/cproton/extension.py¬†copes the php extension, cproton.so that we built earlier out of the app .php-extrensions directory into the correct place for a PHP 5.4 runtime to pick it up.¬† The PHP extension depends on the libqpidproton.so.2 shared library, also a product of the proton build, which needs to be copied into the applications lib directory so that the loader will find it.
The build pack is configured as per the documentation by the .bp-config/options.json file which tells the buildpack that this is a worker, using PHP 5.4 and that it should try to load the cproton extension.
"PHP_EXTENSIONS" : ["cproton"]
My PHP worker app.
The only code I had to write is in app.php, which is automatically run by the buildpack.¬† This contains some trivial PHP to extract the connection information from VCAP_SERVICES together with some fairly simple and self explanatory code to interact with the qpid proton messenger API.
Runing the app.
To run the application, clone the front-end app¬† (implemented in node.js), add twitter keys to it as described in the README and then to push it to Bluemix.¬† Bind¬† the app¬† to an instance of the MQ light service, start it and visit its URL.
Then push an instance of the PHP worker to IBM Bluemix, bind it to the same instance of MQ Light and start it.
You should see twitter messages being processed in real time. If you tail the logs from the worker you should see it processing messages from the front end.
What this blog post demonstrates is that it is certainly possible to interact with MQ Light using PHP in Bluemix but, reflecting the unsupported status of PHP both by MQ Light and bluemix, it is not without its wrinkles.¬† Is PHP support interesting to you? If it is then please let us know either on the MQ Light Forum or in Answers.¬† Much better, integrated and simple PHP support is certainly something we are interested in and we’ll prioritise based on feedback.