24 czerwca 2021

RabbitMq cz.1 – Hello World

Po bardzo długiej przerwie od pisania powracam małymi krokami.

Myślę że większość z nas prędzej, lub później spotka się z potrzebą wymiany informacji pomiędzy różnymi aplikacjami.

Sytuacja życiowa może wyglądać w sposób następujący. Posiadamy api które odbiera request z żądaniem wygenerowania raportu. Nasze api więc przy pomocy RabbitMq może poinformować o tym program przeznaczony do tego celu, który to jest na zupełnie innej maszynie, napisany przy użyciu innych technologii.

Z mojego podwórka mogę przytoczyć trochę ogólnikowo mój case. W centrali telefonicznej nastąpiło pewne zdarzenie, informacja o tym jest przekazana do RabbitMq. Skrypt na innym serwerze jest konsumentem, każdorazowo po otrzymaniu nowej informacji, przetwarza ją i przekazuje dalej do odpowiedniej osoby przy użyciu Websockets.

Możemy wymienić informacje różnymi metodami, my sprawdzimy jak dokonać tego za pomocą RabbitMq oraz dockera.

Dziś postanowiłem napisać krótki wpis o tym, jak możemy zacząć pracę z RabbitMq, przekazując prosty string „Hello World”. Aby zacząć, należy zainstalować wcześniej kilka narzędzi, nie będę opisywał wszystkiego bowiem 1500 poradników znaleźć możemy w internecie.

Zacznijmy więc od konfiguracji dockera.

Na wstępie stwórzmy plik o nazwie „docker-compose.yml

version: '3'

services:
    php:
        build:
            context: .
            dockerfile: ./php
        volumes:
            - ./rabbit:/rabbit
        networks:
            - code-network
    rabbitmq:
        image: rabbitmq:3-management-alpine
        container_name: 'rabbitmq'
        ports:
            - 5672:5672
            - 15672:15672
        networks:
            - code-network

networks:
    code-network:
        driver: bridge

Jesteśmy zmuszeni do stworzenia kolejnego pliku, tym razem o nazwie „php„, możemy dowolnie modyfikować tą nazwę, podając jej inną nazwę wewnątrz powyższego pliku:

services:
    php:
        build:
            context: .
            dockerfile: ./{własna_nazwa_pliku}
        volumes:

Zawartość pliku „php„:

FROM php:7-fpm

RUN apt-get update \
    && apt-get install -y \
        librabbitmq-dev \
        libssh-dev \
    && pecl install amqp \
    && docker-php-ext-enable amqp

RUN curl -sS https://getcomposer.org/installer | php \
        && mv composer.phar /usr/local/bin/ \
        && ln -s /usr/local/bin/composer.phar /usr/local/bin/comp

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /

ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}"

Po odpaleniu naszej wirtualnej maszyny, jesteśmy w stanie zalogować się do panelu rabbita, wpiszmy w tym celu w pasku adresu naszej przeglądarki taki adres:

http://127.0.0.1:15672

Domyślne dane logowania to:
– login: quest
– hasło: quest

Po zalogowaniu się do panelu rabbita, zalecam stworzenie nowego użytkownika w zakładce „admin”.

Proces ten został opisany tutaj:

https://www.ge.com/digital/documentation/proficy-plant-applications/version81/t_gsg_configuring_user_in_RabbitMQ.html

W zakładce „queues” stwórzmy nową kolejkę, ja swoją nazwałem „phpmessage„. Typ kolejki „classic”.

Skrypt php

Wszystko mamy przygotowane, czas na wykonanie skryptu php.

Musimy zalogować się do naszej maszyny wirtualnej php aby odpalić nasz skrypt który zaraz wykonamy, ale również zainstalować przy pomocy composera niezbędną w tym celu bibliotekę.

Po zalogowaniu się więc do linii komend naszej maszyny, należy przejść do katalogu w którym zainstalowana jest nasza aplikacja, jeśli nie zmienimy podanych plików dockera, będzie to katalog „rabbit”.

W nim wykonujemy polecenie

composer ini

Przechodzimy przez prosty formularz z pytaniami o nazwę aplikacji itd.
Po przejściu przez listę pytań, zostanie automatycznie stworzony plik „composer.json”.

Możemy teraz wydać polecenie:

composer require php-amqplib/php-amqplib

Możemy również otworzyć plik „composer.json” i ręcznie dopisać do indeksu „require” nazwę biblioteki oraz jej wersję:

"require": {
        "php-amqplib/php-amqplib": "^3.0"
    }

Teraz wystarczy ostatnie polecenie:

composer install

Pobrana zostanie interesująca nas biblioteka oraz zaktualizowany/stworzony zostanie plik „autoload.php„.

Stwórzmy plik o nazwie „get.php„.

Załadujmy w nim nasz autoloader:

require_once('vendor/autoload.php');

Wskażmy bibliotekę jaką będziemy używać:

use PhpAmqpLib\Connection\AMQPStreamConnection;

Połączmy się z naszym rabbitem:

$connection = new AMQPStreamConnection('rabbitmq', 5672, 'php', 'php');

Pierwszy parametr to host z jakim się łączymy, jest to docker więc podajemy nazwę „rabbitmq„, port oraz nazwę użytkownika i hasło (dane które podaliśmy przy tworzeniu nowego użytkownika w zakładce „admin„).

Jak widać powyżej, ja stworzyłem użytkownika o nazwie „php” oraz takim samym haśle.

Możemy w tej chwili uruchomić nasz skrypt podając w wierszu poleceń naszej maszyny wirtualnej:

php get.php

Jeśli to polecenie nie zakończy się błędem, oznacza to, że nawiązaliśmy połączenie z sukcesem.

Zalecam również sprawdzenie w zakładce „connections” panelu rabbita zobaczyć czy widnieje tam nasz skrypt na liście połączeń.

Następnym krokiem jest wykonanie funkcji która pobierze naszą wiadomość z rabbita jako parametr oraz wyświetli w terminalu:

$echoMessage = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
};

Deklarujemy jakiej kolejki będziemy nasłuchiwać oraz, gdy pojawi się nowa wiadomość jaką funkcję chcemy uruchomić:

$channel->basic_consume('phpmessage', '', false, true, false, false, $echoMessage);

Jeśli połączenie jest otwarte damy pętlę while w celu oczekiwania na nowe wiadomości:

while ($channel->is_open()) {
    $channel->wait();
}

Po zakończeniu całości, zamykamy połączenie oraz kanał:

$channel->close();
$connection->close();

Cały plik wygląda następująco:

<?php

require_once('vendor/autoload.php');

use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('rabbitmq', 5672, 'php', 'php');
$channel = $connection->channel();

$echoMessage = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
};

$channel->basic_consume('phpmessage', '', false, true, false, false, $echoMessage);

while ($channel->is_open()) {
    $channel->wait();
}

$channel->close();
$connection->close();

W tym momencie, uruchomić możemy ponownie nasz skrypt „get.php” wydając polecenie:

php get.php

Nasz program słucha i czeka na informacje, gdy tylko ją otrzyma, wywoła funkcję zawartą w zmiennej „$echoMessage„.

Ostateczny test

Zalogujmy się ponownie do panelu RabbitMq, znajdziemy go pod adresem:
http://127.0.0.1:15672

Przejdźmy do zakładki „Queues„, następnie wybierzmy kolejkę o nazwie „phpmessage” (chyba że nazwaliśmy ja inaczej).
Pod nagłówkiem „Publish message” możemy wysłać nową wiadomość, przykładowo „Hello World„.

Zapraszam do zapoznania się z powyższym filmem, który jest uzupełnieniem powyższego wpisu.