RabbitMQ
RabbitMQ is a server which implements AMQP (Advanced Message Queuing Protocol). It’s general purpose is to help with storing the data for later processing.
Thanks to the fact we can significantly lower the response time for our system (i.e. website) and present the results after the request have been carried out.
RabbitMQ installation.
We’ll start with rabbitmq server and amqp library installation on debian server. After this step we’ll have server running in the backgroup and php available (but it may be necessary to restart web server serivce – i.e. service apache2 restart).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
root@debian-template:~# apt-get install php-amqplib rabbitmq-server Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: erlang-asn1 erlang-base erlang-corba erlang-crypto erlang-diameter erlang-edoc erlang-eldap erlang-erl-docgen erlang-eunit erlang-ic erlang-inets erlang-mnesia erlang-nox erlang-odbc erlang-os-mon erlang-parsetools erlang-percept erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssh erlang-ssl erlang-syntax-tools erlang-tools erlang-webtool erlang-xmerl libltdl7 libodbc1 libsctp1 lksctp-tools php5-common Suggested packages: erlang erlang-manpages erlang-doc xsltproc fop erlang-ic-java erlang-observer libmyodbc odbc-postgresql tdsodbc unixodbc-bin php5-user-cache The following NEW packages will be installed: erlang-asn1 erlang-base erlang-corba erlang-crypto erlang-diameter erlang-edoc erlang-eldap erlang-erl-docgen erlang-eunit erlang-ic erlang-inets erlang-mnesia erlang-nox erlang-odbc erlang-os-mon erlang-parsetools erlang-percept erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssh erlang-ssl erlang-syntax-tools erlang-tools erlang-webtool erlang-xmerl libltdl7 libodbc1 libsctp1 lksctp-tools php-amqplib php5-common rabbitmq-server 0 upgraded, 33 newly installed, 0 to remove and 115 not upgraded. Need to get 24.8 MB of archives. After this operation, 41.1 MB of additional disk space will be used. Do you want to continue? [Y/n] (.....) Preparing to unpack .../php5-common_5.6.20+dfsg-0+deb8u1_amd64.deb ... Unpacking php5-common (5.6.20+dfsg-0+deb8u1) ... Selecting previously unselected package php-amqplib. Preparing to unpack .../php-amqplib_2.4.1-1_all.deb ... Unpacking php-amqplib (2.4.1-1) ... Selecting previously unselected package rabbitmq-server. Preparing to unpack .../rabbitmq-server_3.3.5-1.1_all.deb ... Unpacking rabbitmq-server (3.3.5-1.1) ... Processing triggers for man-db (2.7.0.2-5) ... Processing triggers for systemd (215-17) ... Setting up libltdl7:amd64 (2.4.2-1.11) ... Setting up libodbc1:amd64 (2.3.1-3) ... Setting up libsctp1:amd64 (1.0.16+dfsg-2) ... Setting up erlang-base (1:17.3-dfsg-4) ... Searching for services which depend on erlang and should be started...none found. Setting up erlang-asn1 (1:17.3-dfsg-4) ... Setting up erlang-mnesia (1:17.3-dfsg-4) ... Setting up erlang-runtime-tools (1:17.3-dfsg-4) ... Setting up erlang-crypto (1:17.3-dfsg-4) ... Setting up erlang-public-key (1:17.3-dfsg-4) ... Setting up erlang-ssl (1:17.3-dfsg-4) ... Setting up erlang-inets (1:17.3-dfsg-4) ... Setting up erlang-corba (1:17.3-dfsg-4) ... Setting up erlang-syntax-tools (1:17.3-dfsg-4) ... Setting up erlang-diameter (1:17.3-dfsg-4) ... Setting up erlang-xmerl (1:17.3-dfsg-4) ... Setting up erlang-edoc (1:17.3-dfsg-4) ... Setting up erlang-eldap (1:17.3-dfsg-4) ... Setting up erlang-erl-docgen (1:17.3-dfsg-4) ... Setting up erlang-eunit (1:17.3-dfsg-4) ... Setting up erlang-ic (1:17.3-dfsg-4) ... Setting up erlang-odbc (1:17.3-dfsg-4) ... Setting up erlang-snmp (1:17.3-dfsg-4) ... Setting up erlang-os-mon (1:17.3-dfsg-4) ... Setting up erlang-parsetools (1:17.3-dfsg-4) ... Setting up erlang-percept (1:17.3-dfsg-4) ... Setting up erlang-ssh (1:17.3-dfsg-4) ... Setting up erlang-webtool (1:17.3-dfsg-4) ... Setting up erlang-tools (1:17.3-dfsg-4) ... Setting up erlang-nox (1:17.3-dfsg-4) ... Setting up lksctp-tools (1.0.16+dfsg-2) ... Setting up php5-common (5.6.20+dfsg-0+deb8u1) ... Creating config file /etc/php5/mods-available/pdo.ini with new version Creating config file /etc/php5/mods-available/opcache.ini with new version Setting up php-amqplib (2.4.1-1) ... Setting up rabbitmq-server (3.3.5-1.1) ... Adding group `rabbitmq' (GID 114) ... Done. Adding system user `rabbitmq' (UID 109) ... Adding new user `rabbitmq' (UID 109) with group `rabbitmq' ... Not creating home directory `/var/lib/rabbitmq'. Processing triggers for libc-bin (2.19-18) ... Processing triggers for systemd (215-17) ... root@debian-template:~# |
RabbitMQ test.
In Debian Linux distribution, package php-amqplib brings usefull example (available in /usr/share/doc/php-amqplib/examples/)
We’ll use one of the exapmle files and move it to /var/www/html, so it will be server by the apache2 server as the default site when we access our server (http://ourIPaddress/).
We’ll take the following steps:
- copy all the files from /usr/share/doc/php-amqplib/examples/ to /var/www/html/amqp
- change the ownership of the directory and files in var/www/html/amqp to www-data user and www-data group (in the example below we work on root account, which is not best, but fair enough for education purposes on our local virtual machine)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
root@debian-template:~# cd /usr/share/doc/php-amqplib/examples/ root@debian-template:/usr/share/doc/php-amqplib/examples# (tar cvf - ./*) | (cd /var/www/html/; mkdir amqp; cd amqp; tar xv) ./amqp_consumer_exclusive.php ./amqp_consumer_fanout_1.php ./amqp_consumer_fanout_2.php ./amqp_consumer_non_blocking.php ./amqp_consumer.php ./amqp_ha_consumer.php ./amqp_publisher_exclusive.php ./amqp_publisher_fanout.php ./amqp_publisher.php ./amqp_publisher_with_confirms.php ./basic_cancel.php ./basic_get.php ./basic_nack.php ./basic_return.php ./batch_publish.php ./config.php ./e2e_bindings.php ./queue_arguments.php ./ssl_connection.php ./amqp_consumer_exclusive.php ./amqp_consumer_fanout_1.php ./amqp_consumer_fanout_2.php ./amqp_consumer_non_blocking.php ./amqp_consumer.php ./amqp_ha_consumer.php ./amqp_publisher_exclusive.php ./amqp_publisher_fanout.php ./amqp_publisher.php ./amqp_publisher_with_confirms.php ./basic_cancel.php ./basic_get.php ./basic_nack.php ./basic_return.php ./batch_publish.php ./config.php ./e2e_bindings.php ./queue_arguments.php ./ssl_connection.php root@debian-template:/usr/share/doc/php-amqplib/examples# cd /var/www/html/ root@debian-template:/var/www/html# chown www-data.www-data /var/www/html/amqp/ -R |
php-amqplib library requires adding some dependencies by using Composer tool.
We’ll take the following steps to accomplish the task:
- install curl i git tools
- create the composer.json file
- we’ll run the composer (downloading it with curl command and piping the output of curl to php interpreter). This step will create composer.phar file.
- finally we run composer.phar with install option, which will install dependencies.
Note:
- we took the steps in /var/www/html as current working directory. All the files located in /var/www/html/amqp will refer to this catalogue and look for vendor subdirectory (available after fulfilling first three steps)
1 |
root@debian-template:/var/www/html# apt-get install git curl |
1 2 3 4 5 6 7 8 9 10 11 |
root@debian-template:/var/www/html# cat > composer.json <<EOF { "require": { "videlalvaro/php-amqplib": "2.2.*" } } EOF root@debian-template:/var/www/html# curl -sS https://getcomposer.org/installer | php (...) root@debian-template:/var/www/html# php composer.phar install (...) |
Queue handling .
In /var/www/html/amqp/ directory we place the example file for different queue handling.
We’ll present how to run one of this files, but we first need to modify configuration.
In config.php, we change AMQP_DEBUG to false (so there’ll be no debugging information and the results of our script will be human readable. Of course if we encounter any problem with our script or the library we may change it to true):
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php require_once __DIR__ . '/../vendor/autoload.php'; define('HOST', 'localhost'); define('PORT', 5672); define('USER', 'guest'); define('PASS', 'guest'); define('VHOST', '/'); //If this is enabled you can see AMQP output on the CLI define('AMQP_DEBUG', false); |
Let’s check the content of basic_get.php (presented below, but with all comments removed). This script first sends ‘test message’ to a queue, and the retrieves it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php include(__DIR__ . '/config.php'); use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage; $exchange = 'basic_get_test'; $queue = 'basic_get_queue'; $conn = new AMQPConnection(HOST, PORT, USER, PASS, VHOST); $ch = $conn->channel(); $ch->queue_declare($queue, false, true, false, false); $ch->exchange_declare($exchange, 'direct', false, true, false); $ch->queue_bind($queue, $exchange); $toSend = new AMQPMessage('test message', array('content_type' => 'text/plain', 'delivery_mode' => 2)); $ch->basic_publish($toSend, $exchange); $msg = $ch->basic_get($queue); $ch->basic_ack($msg->delivery_info['delivery_tag']); var_dump($msg->body); $ch->close(); $conn->close(); |
ToDo:
- Copy the basic_get.php to two separate files put1.php i get2.php.
- Modify put1.php so it will only add a message to a queue (removing the retrieving part)
- Modify get1.php so it will only fetch the message from a queu (removing the adding part)